mysql 字符串比较_Mysql字符类型比较

本文详细介绍了Mysql中binary、char、varchar类型的比较,以及它们与uuid存储和比较的特点。在binary比较中,基于字节值,而char基于字符,binary和char(BINARY)在特定情况下等价。对于uuid,存储空间测试表明,无论字符集如何,占用空间相同。业务主键使用uuid虽存储空间稍大,但能屏蔽业务量信息。char和varchar在存储和检索时处理空格方式不同,比较时忽略尾部空格。binary和varbinary在比较时所有字节都参与,且varbinary存储不填补末尾0x00。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 binary和char比较:

binary 字节为单位,char字符为单位,字符占几个字节取决于字符集

binary  比较规则基于字节值,char基于字符,即使是_bin的比较规则

范围都0-255字节,char对于不同字符集,可以存取的字节数不同

排序和比较规则都会根据字符码值,而不是词典顺序,如果采用binary那么是区分大小写的,和我们常用的utf8_general_ci相冲突

相同特性,摘自官方文档:

Specifying the CHARACTER SET binary attribute for a character data type causes the column

to be created as the corresponding binary data type: CHAR becomes BINARY, VARCHAR becomes VARBINARY , and TEXT becomes BLOB . For the ENUM and SET data types, this does not occur;

以下两种表定义是等义的:

CREATE TABLE t

(

c1 VARCHAR(10) CHARACTER SET binary,

c2 TEXT CHARACTER SET binary,

c3 ENUM('a','b','c') CHARACTER SET binary

);

CREATE TABLE t

(

c1 VARBINARY(10),

c2 BLOB,

c3 ENUM('a','b','c') CHARACTER SET binary

);

占用空间比较,测试uuid在不同字符集下的占用空间,主要是考虑到uuid是否适合业务主键的问题

创建4个表,第一个表是utf8字符集比较规则是utf8_bin

mysql> create table tc1(synid char(36) character set utf8 collate utf8_bin);

Query OK, 0 rows affected (0.07 sec)

mysql> create table tc2(synid char(36) character set utf8 collate utf8_general_ci);

Query OK, 0 rows affected (0.08 sec)

mysql> create table tc3(synid char(36) character set binary);

Query OK, 0 rows affected (0.06 sec)

mysql> create table tc4(synid binary(36));

Query OK, 0 rows affected (0.11 sec)

插入相同的数据1000条数据,表大小相同:

mysql> SELECT table_name,SUM(data_length) AS data_length

-> FROM information_schema.TABLES WHERE

-> table_name IN ('tc1','tc2','tc3','tc4')

-> GROUP BY table_name;

+------------+----------------+

| table_name | data_length |

+------------+----------------+

| tc1        |        1589248 |

| tc2        |        1589248 |

| tc3        |        1589248 |

| tc4        |        1589248 |

+------------+----------------+

4 rows in set (0.00 sec)

对于相同的原因主要有两方面:

Basic Latin letters, digits, and punctuation signs use one byte,mysql支持的utf8编码对于基本的拉丁字母、数字、标点符号用一个字节

A UUID is a 128-bit number represented by a utf8 string of five hexadecimal numbers in aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee format。利用uuid函数生成的uuid是32个十六进制数表示的字符串(由0-9和a-f组成),中间有4个横线分隔,总共有36个字符。

当时测试以上问题主要是为了讨论uuid适不适合做业务主键,以下是我的一些总结:

我们物理主键采用int自增,但是业务主键采用uuid

这样虽然不够友好,但是可以屏蔽从自增id上获取的业务量。

存储上虽然比int要多32个字节,但是现在存储很廉价。我们可以通过去掉无意义的'-'分隔符(32字节),或者采用uuid_short()(20字节)获取全局唯一标识

效率依赖于业务,如果是拿uuid查询,那么说明区分度很高了,建立索引效率不成问题。uuid做索引会比主键索引大很多,但在合理内存范围内就不会产生多余IO

和SQLServer保持兼容,如果合并停车记录两张表,显然会冲突,用uuid则不会。为了保证兼容sqlserver的Chinese_PRC_CI_AS,建议采用字符集是utf8,比较规则是utf8_general_ci

需要注意的是does not work with statement-based replication,主从复制时,基于语句级别的binlog不支持uuid()函数

二、 char和varchar

允许创建char(0)类型字段,用于某个字段存在,但是并不用它的值,只存储两个值:null和''

范围是0-65535字节,可以存储多少个字符由字符集决定。当字段类型小于255字节时,前缀会存储1个字节;当字段长度大于255时,前缀会存储2个字节

当char被存储时,会自动在尾部填充空格到设置的长度。varchar会保留空格。当char被检索时,会移除尾部空格,除非设置了PAD_CHAR_TO_FULL_LENGTH

b7faec538784b62ccc2dce7dc5935b38.png

当char被检索时,会移除尾部空格,除非设置了PAD_CHAR_TO_FULL_LENGTH;varchar在检索时会保留尾部空格

9919ca28aff558eb017a80ebd4099594.png

在严格的SQL mode下,char和varchar类型字段超过最大长度会截断并产生警告,如果截断的是非空字符,那么会阻止插入并报错,在任何SQL mode下,varchar会截断超出长度的空格,char则会截断尾部所有空格

char和varchar的比较都是忽略尾部空格的,但是除了将尾部空格作为like匹配条件的

f2882f1e18afdf2280d9885e8ed53f43.png

注意:需要注意的是,varchar显示是不截断尾部空格的,但在比较的时候忽略空格的,此外varchar存储时会去掉尾部空格,如果该字段被定义成唯一建或主键,去除结尾空格后相同的字符串会违反唯一性约束

三、 binary和vbinary

binary和vbinary在超过最大设置长度时,在非strict SQL mode下,那么会自动截断并警告;在strict SQL mode下,会阻止插入,并报错。

binary存储时自动填充值\0(0x00),满足指定长度,例如,char(3),'a '插入变成'a \0','a'变成'a\0\0'。在检索的时候,并不去掉结尾的填充值。

varbinary,存储时不会填补\0,检索时不会去掉结尾\0

binary和varbinary在比较时,包括order by和distinct,所有的字节都是有意义的。注0x00

注意:同样,vbinary在需要注意在存储时去掉尾部\0,如果该字段被定义成唯一建或主键,去除结尾\0后相同的字符串会违反唯一性约束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值