MySQL CHAR和VARCHAR存储、读取时的差别
导读
你真的知道char和varchar类型在存储和读取时的区别吗?
还是先抛几条结论吧:
1、存储的时候,char总是会补足空格后再存储,不管用户插入数据时尾部有没有包含空格。
2、存储的时候,varchar不会先补足空格后再存储,但如果是用户在插入时特地加了空格那就会如实存储,而不会给删除。
3、读取数据时,char总是会删除尾部空格(哪怕是写入时包含空格)。
4、读取数据时,varchar总是如实取出之前存入的值(如果存储时尾部包含空格,就会继续保留着,不会像char那样删除尾部空格)。
下面是测试验证过程。
1、测试char类型
表结构:
create table `tchar` ( `id` int(10) unsigned not null default '0', `c1` char(20) not null default '', primary key (`id`) ) engine=innodb default charset=utf8mb4;
插入几条记录:
insert into tchar values (1, concat('a', repeat(' ',19))); insert into tchar values (2, concat(' ', repeat('a',19))); insert into tchar values (3, 'a'); insert into tchar values (4, ' '); insert into tchar values (5, '');
查看存储结构:
(1) infimum record offset:99 heapno:0 ... (2) supremum record offset:112 heapno:1 ... (3) normal record offset:126 heapno:2 ... <- id=1 (4) normal record offset:169 heapno:3 ... <- id=2 (5) normal record offset:212 heapno:4 ... <- id=3 (6) normal record offset:255 heapno:5 ... <- id=4 (7) normal record offset:298 heapno:6 ... <- id=5
看到这坨东西有点懵是不是,还记得我给你们安利过的一个工具不,看这里:innblock | innodb page观察利器。
可以看到,无论我们存储多长的字符串进去,每条记录实际都是占用43(169-126=43)字节。由此结论1成立。
简单说下,43字节的由来:
db_trx_id, 6字节。
db_roll_ptr, 7字节。
id, int, 4字节。
c1, char(20), 20字节;因为是char类型,还需要额外1字节。
每条记录总是需要额外5字节头信息(row header)。
这样总的加起来就是43字节了。
再看下读取tchar表的结果:
select id,concat('000',c1,'$$$'),length(c1) from tchar ; +----+----------------------------+------------+ | id | concat('000',c1,'$$$') | length(c1) | +----+----------------------------+------------+ | 1 | 000a$$$ | 1 | <- 删除尾部空格 | 2 | 000 aaaaaaaaaaaaaaaaaaa$$$ | 20 | | 3 | 000a$$$ | 1 | | 4 | 000$$$ | 0 | <- 删除尾部空格,结果和id=5一样 | 5 | 000$$$ | 0 | +----+----------------------------+------------+
2、测试varchar类型
表结构:
create table `tvarchar` ( `id` int(10) unsigned not null default '0', `c1` varchar(20) not null default '', primary key (`id`) ) engine=innodb default charset=utf8mb4
插入几条记录:
insert into tvarchar values (1, concat('a', repeat(' ',19))); insert into tvarchar values (2, concat(' ', repeat('a',19))); insert into tvarchar values (3, 'a'); insert into tvarchar values (4, ' '); insert into tvarchar values (5, ''); insert into tvarchar values (6, '');
查看存储结构:
(1) infimum record offset:99 heapno:0 ... (2) supremum record offset:112 heapno:1 ... (3) normal record offset:126 heapno:2 ... <- id=1 (4) normal record offset:169 heapno:3 ... <- id=2 (5) normal record offset:212 heapno:4 ... <- id=3 (6) normal record offset:236 heapno:5 ... <- id=4 (7) normal record offset:260 heapno:6 ... <- id=5 (8) normal record offset:283 heapno:7 ... <- id=6
可以看到,几条记录的字节数分别是:43、43、24、24、23、23(最后一条记录和id=5那条记录一样)。
对上面这个结果有点诧异是不是,尤其是id=1的记录(插入的是'a…后面19个空格'),居然也要消耗43字节,这就佐证了上面的结论2。
同样的,id=3和id=4这两条记录都是占用24字节,而id=5和id=6这两条记录都是占用23字节(没有额外存储字符串的字节数,只有id列4个字节)。
再看下读取tvarchar表的结果:
select id,concat('000',c1,'$$$'),length(c1) from tvarchar; +----+----------------------------+------------+ | id | concat('000',c1,'$$$') | length(c1) | +----+----------------------------+------------+ | 1 | 000a $$$ | 20 | <- 读取结果中没有删除尾部的空格 | 2 | 000 aaaaaaaaaaaaaaaaaaa$$$ | 20 | | 3 | 000a$$$ | 1 | | 4 | 000 $$$ | 1 | <- 读取结果中没有删除此空格 | 5 | 000$$$ | 0 | | 6 | 000$$$ | 0 | +----+----------------------------+------------+
总的来说,可以总结成两条结论:
1、从读取的结果来看,char类型列看起来像是在存储时把空格给吃了,但实际上只是在读取时才给吃了(显示层面上把空格删除了)。
2、从读取的结果来看,varchar类型列看起来像是反倒保留了多余的空格,实际上也是只在读取时才恢复这些空格(但实际物理存储时还是会删掉这些空格)。
最后,来看下文档里怎么说的:
when char values are stored, they are right-padded with spaces to the
specified length. 简言之,char列在存储时尾部加空格补齐长度。when char values are retrieved, trailing spaces are removed unless the
pad_char_to_full_length sql mode is enabled.
简言之,char列在读取时会去掉尾部空格,除非设置sql_mode值pad_char_to_full_length=1。varchar values are not padded when they are stored.
简言之,存varchar时尾部不加空格。trailing spaces are retained when values are stored and retrieved, in
conformance with standard sql. 简言之,读取varchar时会显示空格。
以上测试使用的版本及环境:
mysql> select version()\g ... version(): 8.0.15 mysql> select @@sql_mode\g ... @@sql_mode: only_full_group_by,strict_trans_tables,no_zero_in_date,no_zero_date,error_for_division_by_zero,no_engine_substitution
参考文档
11.4.1 the char and varchar types,
以上就是mysql char和varchar存储的差别的详细内容,更多关于mysql char和varchar的资料请关注其它相关文章!
推荐阅读
-
MySQL CHAR和VARCHAR存储、读取时的差别
-
MYSQL中 char 和 varchar的区别
-
MySQL中varchar和char类型的区别
-
深入char、varchar、text和nchar、nvarchar、ntext的区别详解_MySQL
-
mysql varchar和char创建索引的大小计算_MySQL
-
ajax请趋同一个文件和多个文件时,读取速度有没有大的差别
-
MySQL中VARCHAR和CHAR格式数据的区别
-
mysql varchar和char创建索引的大小计算_MySQL
-
ajax请趋同一个文件和多个文件时,读取速度有没有大的差别
-
ajax请趋同一个文件和多个文件时,读取速度有没有大的差别