CHAR-定长与变长字符类型之间的终极选择指南-MySQL-存储秘密揭示-vs.-VARCHAR (char定义的是什么)
CHAR 和 VARCHAR 数据类型在存储和检索方式上具有相似之处,但在最大长度以及是否保留尾随空格方面存在差异。
一、存储方面
1、存储对比
CHAR 和 VARCHAR 类型的声明都包含一个长度,表示要存储的最大字符数。例如,CHAR(30) 可以容纳最多 30 个字符。CHAR 列的长度在创建表时被固定为您声明的长度。长度可以是从 0 到 255 的任何值。当存储 CHAR 值时,它们会被右填充到指定的长度。当检索 CHAR 值时,除非启用了 PAD_CHAR_TO_FULL_LENGTH SQL 模式(默认未启用),否则会删除尾随空格。
VARCHAR 列中的值是可变长度字符串。长度可以指定为 0 到 65,535 的值。VARCHAR 的有效最大长度取决于最大行大小(65,535 字节,这个大小被所有列共享)和所使用的字符集。
2、具体对比
假设当前一个表中包含类型为 char(4) 及 varchar(4) 的列(假设该列使用单字节字符集如 latin1),则,存储所需的大小对比如下:
值 | CHAR(4) | VARCHAR(4) |
---|---|---|
a | 4 字节 | 1 字节 |
张三 | 12 字节 | 6 字节 |
tc一 | 8 字节 | 5 字节 |
二、显示及检索对比
本文后续案例是在 utf8 的字符集的实例上进行展示的。
1、默认 SQL 模式
默认未开启 PAD_CHAR_TO_FULL_LENGTH SQL 模式的情况下,char 及 varchar 的显示几乎没有区别,例如:
>create table tb_char(
> id int primary key auto_increment,
> c_char char(10),
> c_varchar varchar(10)
>);
Query OK, 0 rows affected (0.01sec)
>insert into tb_char(c_char, c_varchar) values (a, a), (张三, 张三), (tc一, tc一);
Query OK, 3 rows affected (0.00sec)
Records: 3 Duplicates: 0 Warnings: 0
查询显示如下:
>select from tb_char;
+----+--------+-----------+
| id | c_char | c_varchar |
+----+--------+-----------+
| 1 | a | a |
| 2 | 张三 | 张三 |
| 3 | tc一 | tc一 |
+----+--------+-----------+
3 rows in set (0.00sec)
查看长度如下:
>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.00sec)
从显示结果来看,char 与 varchar 在此时看上去是一致的,即:
- 查询时,char 类型的
mysql中数据类型char和varchar的区别
char是一种固定长度的类型,varchar则是一种可变长度的类型,它们的区别是:char(M)类型的数据列里,每个值都占用M个字节,如果某个长度小于M,MySQL就会在它的右边用空格字符补足.(在检索操作中那些填补出来的空格字符将被去掉)在varchar(M)类型的数据列里,每个值只占用刚好够用的字节再加上一个用来记录其长度的字节(即总长度为L+1字节).在MySQL中用来判断是否需要进行对据列类型转换的规则1、在一个数据表里,如果每一个数据列的长度都是固定的,那么每一个数据行的长度也将是固定的.2、只要数据表里有一个数据列的长度的可变的,那么各数据行的长度都是可变的.3、如果某个数据表里的数据行的长度是可变的,那么,为了节约存储空间,MySQL会把这个数据表里的固定长度类型的数据列转换为相应的可变长度类型.例外:长度小于4个字符的char数据列不会被转换为varchar类型
MySQL 数据表优化设计(三):CHAR 和 VARCHAR 怎么选?
VARCHAR 和 CHAR 是两种主要的字符串类型,用于存储字符。不幸的是,由于实现的方式依赖于存储引擎,因此很难解释这些字符串在磁盘和内存中如何存储,除了除了常用的 InnoDB 和 MyISAM 外,假设你使用了其他存储引擎,应当仔细阅读存储引擎的文档。
VARCHAR 存储可变长度的字符串,也是最常用的字符数据类型。相比固定长度的类型,VARCHAR 所需的存储空间更小,它会尽可能少地使用存储空间(例如,短的字符串占据的空间)。对于 MyISAM 来说,如果创建表的时候指定了 ROW_FORMAT=FIXED 的话,那么会使用固定的空间存储字段而导致空间浪费。VARCHAR 使用1-2个额外的字节存储字符串的长度:当最大长度低于255字节的时候使用1个字节,如果更多的话就使用2个字节。因此,拉丁字符集的 VARCHAR(10)会使用11个字节的存储空间,而 VARCHAR(1000)则会使用1002个字节的存储空间。
VARCHAR 由于能够节省空间,因此可以改善性能。但是,由于长度可变,当更新数据表的时候数据行的存储空间会变化,这一定程度上会带来额外的开销。如果数据行的长度导致原有的存储位置无法存放,那么不同的存储引擎会做不同的处理。例如 MyISAM 可能产生数据行的碎片,而 InnoDB 需要进行磁盘分页来存放更新后的数据行。
通常,如果最大的列长度远远高于平均长度的话(例如可选的备注字段),使用 VARCHAR 是划算的,同时如果更新的频次很低,那么碎片化也不会是一个问题。需要注意的是,如果使用的是 UTF-8字符集,则实际存储的字节长度是根据字符定的。对于中文,推荐的存储字符集是 utf8mb4。
CHAR 类型的长度是固定的,MySQL 会对每个字段分配足够的存储空间。 存储CHAR 类型值的时候,MySQL 会移除后面多出来的空字符 。值是使用空字符进行对齐以便进行比较。对于短的字符串来说,使用 CHAR 更有优势,而如果所有的值的长度几乎一致的话,就可以使用 CHAR。例如存储用户密码的MD5值时使用 CHAR 就更合适,这是因为 MD5的长度总是固定的。同时,对于字段值经常改变的数据类型来说,CHAR 相比 VARCHAR 也更有优势,因为 CHAR 不会产生碎片。对于很短的数据列,使用 CHAR 比 VARCHAR更高效,例如使用CHAR(1)存储逻辑值的 Y 和 N,这种情况下只需要1个字节,而 VARCHAR 需要2个字节。 对于移除空字符这个特性会感觉奇怪,我们举个例子:
按上面的结果插入数据表后,string2中的前置空格不会移除,但使用 CHAR 类型存储时,string3尾随空格会被移除,使用 SQL 查询结果来检验一下:
得出来的结果如下,可以看到 CHAR 类型的 string3后面的空格被移除了,而 VARCHAR类型的没有。这种情况大多数时候不会有什么问题,实际在应用中也经常会使用 trim 函数移除两端的空字符,但是如果确实需要存储空格的时候,那就需要注意不要选择使用 CHAR 类型:
数据如何存储是由存储引擎决定的,而且存储引擎处理固定长度和可变长度的数据的方式并不相同。Memory 引擎使用固定大小的行,因此它需要分配最大可能的存储空间——即便数据长度是可变的。但是,对于字符串的对齐和空字符截断是由 MySQL 服务端完成的,因此所有存储引擎都是一样的。
与 CHAR 和 VARCHAR 相似的是 BINARY和 VARBINARY,用于存储二进制字节字符,BINARY 的对齐使用字符0的字节值来对齐,并且再获取值的时候不会截断。如果需要使用字符的字节值而不是字符的话,使用 BINARY 会更高效,这是因为比较时,一方面不需要考虑大小写,另一方面是MySQL一次只比较一个字节。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。