mysql char和varchar区别(MySQL CHAR和VARCHAR存储、读取时的差别)
mysql char和varchar区别
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_liISION_BY_ZERO,NO_ENGINE_SUBSTITUTION |
参考文档
11.4.1 The CHAR and VARCHAR Types,https://dev.mysql.com/doc/refman/5.7/en/char.html
以上就是MySQL CHAR和VARCHAR存储的差别的详细内容,更多关于MySQL CHAR和VARCHAR的资料请关注开心学习网其它相关文章!
原文链接:https://blog.p2hp.com/archives/6616
- xampp数据库表在哪个文件夹(XAMPP集成环境中MySQL数据库的使用)
- mysql的连接代码(MySQL 连接查询的原理和应用)
- mysql整体架构设计(MySQL 整体架构介绍)
- mysql 死锁原因(MySQL锁等待与死锁问题分析)
- mysql中修改表的字段名(MySQL 使用SQL语句修改表名的实现)
- mysql数据库死锁原理(MySQL数据库锁机制原理解析)
- mysql 触发器是什么(MySQL触发器的使用)
- mysql的默认数据库例子在哪里(修改MySQL8.0 默认的数据目录快捷操作无配置)
- mysql8.0.12安装教程图解(mysql 8.0.22 zip压缩包版免安装下载、安装配置步骤详解)
- mysqlcount使用方法(详解 MySQL中count函数的正确使用方法)
- php连接mysql需要数据源吗(php连接mysql数据库最简单的实现方法)
- 对mysql性能优化的看法(聊聊MySQL的COUNT的性能,看看怎么最快?)
- mysql中自增字段类型(MySQL数字类型自增的坑)
- mysql获取随机数(MySQL 生成随机数字、字符串、日期、验证码及 UUID的方法)
- mysql的四种关系运算(详解MySQL拼接函数CONCAT的使用心得)
- 如何看idea连接mysql数据库(IDEA 链接Mysql数据库并执行查询操作的完整代码)
- 阿里最新财报公布 三季度营收增长3 ,将增加150亿美元回购额度 在美股价小涨(阿里最新财报公布)
- 赵薇时胖时瘦 最近变美少女 原因在这里 躺着就变瘦(赵薇时胖时瘦最近变美)
- 学会这26种姿势,你就可以和兵哥哥切磋了(你就可以和兵哥哥切磋了)
- 吴彦祖陈冠希 恩怨 ,失去曾让他流泪的女友,终遇走过18年真爱(吴彦祖陈冠希恩怨)
- 痴情男神 吴彦祖 与妻子恋爱8年,结婚10年,家庭幸福美满(痴情男神吴彦祖)
- 成功破圈,小牛电动SQi强势开 跨(小牛电动SQi强势开)
热门推荐
- linux怎么看后台进程(一行代码教你如何隐藏Linux进程)
- php如何异步操作(php链式操作的实现方式分析)
- sql server 判断 null
- vue在html里面怎么展示图片(v-html渲染组件问题)
- mysql双主状态不一致(MySQL GTID主备不一致的修复方案)
- mysql索引失效的几种情况(Mysql 5.6 "隐式转换"导致的索引失效和数据不准确的问题)
- web安全漏洞怎么解决(Web服务器常见8种安全漏洞)
- jQuery 右侧浮动导航菜单
- laravel自定义条件查询(解决laravel groupBy 对查询结果进行分组出现的问题)
- vue项目部署到服务器的nginx(Nginx部署vue项目和配置代理的问题解析)
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9