MySQL存储秘密揭示:CHAR vs.VARCHAR,解锁定长神器的终极选择指南!

CHAR和VARCHAR类型在存储和检索方式上有相似之处,但在最大长度以及是否保留尾随空格方面存在差异 。
一、存储方面1、存储对比CHAR和VARCHAR类型的声明包含一个长度,表示要存储的最大字符数 。例如 , CHAR(30)可以容纳最多30个字符 。
CHAR列的长度在创建表时被固定为您声明的长度 。长度可以是从0到255的任何值 。当存储CHAR值时,它们会被右填充到指定的长度 。当检索CHAR值时,除非启用了PAD_CHAR_TO_FULL_LENGTH SQL模式(默认没启用),否则会删除尾随空格 。
VARCHAR列中的值是可变长度字符串 。长度可以指定为0到65,535的值 。VARCHAR的有效最大长度取决于最大行大?。?5,535字节 , 这个大小被所有列共享)和所使用的字符集 。
2、具体对比假设当前一个表里包含类型为char(4)及varchar(4)的列(假设该列使用单字节字符集如latin1),则,存储所需的大小对比如下:

MySQL存储秘密揭示:CHAR vs.VARCHAR,解锁定长神器的终极选择指南!

文章插图
注:
  • 如果字符集为其他类型(utf8mb4),则根据存储的内容进行换算即可
  • 上例中为了演示,非严格模式时可以截断存储
二、显示及检索对比本文后续案例是在utf8的字符集的实例上进行演示的
1、默认SQL模式默认没开启PAD_CHAR_TO_FULL_LENGTH SQL模式的情况下,char及varchar的显示几乎没有区别,例如:
MySQL> create table tb_char (id int primary key auto_increment, c_char char(10),c_varcharvarchar(10));Query OK, 0 rows affected (0.01 sec)mysql> insert into tb_char (c_char,c_varchar) values ('a','a'),('张三','张三'),('tc一','tc一');Query OK, 3 rows affected (0.00 sec)Records: 3Duplicates: 0Warnings: 0查询显示如下:
mysql> select * fromtb_char;+----+--------+-----------+| id | c_char | c_varchar |+----+--------+-----------+|1 | a| a||2 | 张三| 张三||3 | tc一| tc一|+----+--------+-----------+3 rows in set (0.00 sec)查看长度如下:
mysql> select c_char,c_varchar, length(c_char)len_char,length(c_varchar)len_varchar,char_length(c_char),char_length(c_varchar) from tb_char;+--------+-----------+----------+-------------+---------------------+------------------------+| c_char | c_varchar | len_char | len_varchar | char_length(c_char) | char_length(c_varchar) |+--------+-----------+----------+-------------+---------------------+------------------------+| a| a|1 |1 |1 |1 || 张三| 张三|6 |6 |2 |2 || tc一| tc一|5 |5 |3 |3 |+--------+-----------+----------+-------------+---------------------+------------------------+3 rows in set (0.00 sec)
MySQL存储秘密揭示:CHAR vs.VARCHAR,解锁定长神器的终极选择指南!

文章插图
从显示结果来看 , char与varchar在此时看上去是一致的 , 即:查询时 , char类型的数据会将末尾空格去除 。
此时 , 如果写入末尾带空格的值,则结果会如何呢?
mysql> insert into tb_char (c_char,c_varchar) values ('abc ','abc ');Query OK, 1 row affected (0.01 sec)mysql> select * fromtb_char;+----+--------+-----------+| id | c_char | c_varchar |+----+--------+-----------+|1 | a| a||2 | 张三| 张三||3 | tc一| tc一||4 | abc| abc|+----+--------+-----------+4 rows in set (0.00 sec)mysql> select c_char,c_varchar, length(c_char)len_char,length(c_varchar)len_varchar,char_length(c_char),char_length(c_varchar) from tb_char;+--------+-----------+----------+-------------+---------------------+------------------------+| c_char | c_varchar | len_char | len_varchar | char_length(c_char) | char_length(c_varchar) |+--------+-----------+----------+-------------+---------------------+------------------------+| a| a|1 |1 |1 |1 || 张三| 张三|6 |6 |2 |2 || tc一| tc一|5 |5 |3 |3 || abc| abc|3 |4 |3 |4 |+--------+-----------+----------+-------------+---------------------+------------------------+4 rows in set (0.00 sec)此时,结果出现了不同,char类型的显示依旧将末尾空格去除 , 而varchar则原样显示
MySQL存储秘密揭示:CHAR vs.VARCHAR,解锁定长神器的终极选择指南!

文章插图
如果此时按条件查询‘abc’及‘abc ’,结果会如何?
mysql> select * fromtb_char where c_char ='abc';+----+--------+-----------+| id | c_char | c_varchar |+----+--------+-----------+|4 | abc| abc|+----+--------+-----------+1 row in set (0.00 sec)mysql> select * fromtb_char where c_varchar ='abc';+----+--------+-----------+| id | c_char | c_varchar |+----+--------+-----------+|4 | abc| abc|+----+--------+-----------+1 row in set (0.00 sec)mysql> select * fromtb_char where c_char ='abc ';+----+--------+-----------+| id | c_char | c_varchar |+----+--------+-----------+|4 | abc| abc|+----+--------+-----------+1 row in set (0.00 sec)mysql> select * fromtb_char where c_varchar ='abc ';+----+--------+-----------+| id | c_char | c_varchar |+----+--------+-----------+|4 | abc| abc|+----+--------+-----------+1 row in set (0.00 sec)


推荐阅读