MySQL数据类型之VARCHAR和CHAR使用详解
在设计数据库字段时,字符串类型算是最常见的数据类型之一了,这篇文章带大家深入探讨一下MySQL数据库中VARCHAR
和CHAR
数据类型的基本特性,以及它们之间的区别。
VARCHAR类型
VARCHAR
(Variable Character,可变长度字符)是一种用于存储可变长度字符串的数据类型,可指定存储数据的最大长度。
VARCHAR
是存储字符串最广泛使用的数据类型之一。在定义VARCHAR
字段时,通常使用VARCHAR(n)
格式指定该字段的最大字符容量,其中n
是允许存储的字符最大数量。
每个VARCHAR
字段可以设置一个最大长度值,从1到65535字符(根据MySQL的存储引擎和行格式限制)。不过,该长度会受到一些因素的影响,例如:
- 表的字符集会影响字段的最大字节数。例如,在一个
utf8mb4
表中,每个字符可能占用最多4字节,因此要确保总长度(包括所有列和其它数据)适配MySQL的行存储限制。 - 行存储限制约为65535字节,因此要在表中合理设计列类型。
由于VARCHAR
是一种可变长度类型,数据库会根据实际存储的字符串长度动态分配足够的存储空间,而不是预先分配最大限定长度的空间。除了存储字符串内容外,还会存储一些额外的元数据。
VARCHAR
数据类型使用额外的长度指示字节存储字符串的长度:
- 如果字符串长度小于255字节(一个
VARCHAR
列的定义最大长度为255字符),则使用1个字节来记录长度; - 如果字符串长度超过255字节,则需要2个字节来记录长度。
CHAR类型
CHAR
是MySQL中的一种字符数据类型,最大长度为255个字符,主要用于存储固定长度的字符串。无论插入的数据是否达到了定义的长度,CHAR
都会根据其设定的长度自动填充空格(使用空格补齐),以确保其值总是固定长度。它适用于那些长度固定的、不经常变化的字符串,比如国家代码、省份缩写等。
当一个列的类型定义为CHAR
类型后,列中的内容的长度就是字段定义的长度(字符数)。如果写入CHAR
列中的字符串的长度小于指定的字符长度,MySQL会在源字符串后填充空格一直到指定的长度。当读取CHAR
列中的值时,MySQL会删除后面的空格。
由于CHAR
数据类型采用固定的长度进行存储,因此CHAR
的性能要比VARCHAR
更好。
与VARCHAR
类似,可以使用CHAR(n)
格式来设置字段的最大字符数。如果未指定,n
默认为1。在CHAR
列中存储的值会右对齐用空格填充,因此不管要保存的字符串内容如何,它始终会存储n
个字符。
字符集对字段存储的影响
在数据库设计中,字符集 (Character Set) 和排序规则 (Collation) 是重要的环节。字符集决定了可以存储哪些字符以及每个字符所需的空间,而排序规则决定了数据如何比较和排序。
数据库在日常使用中,除了要支持英文字符之外,还需要支持像西班牙语中的特殊字符 “Ñ”,以及像日语中的 “データベース” 或中文中的 “数据库” 等复杂字符。为此,MySQL提供了多种字符集(charset
),如 latin1
(用于基本英文字符)、utf8
(支持大部分语言)、utf8mb4
(支持完整的 Unicode,包括表情符号)。
字符集不仅影响文本在数据库中的存储形式,也直接影响该字段的存储空间效率。不同字符集的每个字符所需的字节数不同,具体如下:
latin1
: 每个字符固定占用 1 个字节。utf8
: 每个字符占用 1~3 个字节。utf8mb4
: 每个字符占用 1~4 个字节(主要用于完整的 Unicode,例如表情符号)。
在使用VARCHAR
字段时,定义的最大长度n
指的是字符的数量,而不是具体存储所需的字节数。由于字符集影响每个字符的数据大小,因此实际存储时需要考虑字符占用的字节数以及MySQL的行存储限制。
MySQL中,每行数据的最大存储限制为65,535 字节,这包括所有列的数据以及其他额外信息(如长度字节、行偏移量等)。
字符集对CHAR
类型的影响与VARCHAR
类型类似,但由于CHAR
是固定长度存储,影响的性质稍有不同。CHAR
无论存储的字符数量是多少,总会为字段定义的最大长度分配固定空间。例如,在utf8mb4
下,一个CHAR(255)
字段最大可能需要255 × 4 = 1,020字节。
由于CHAR
是固定长度存储类型,在多字节字符集下往往存在空间浪费问题,因此在合理选择字段数据类型时,需要结合应用场景、字符集及数据特性来做对应的设计。
数据可视化的差异
当数据存储到CHAR
字段时,其副作用之一是字符串中的所有尾随空格会在保存时被忽略。实际查询时,MySQL不会返回这些尾随空格,因为它会假设这些空格仅仅是数据类型的填充部分。
用具体的实例演示一下,创建一个表,其中有两个列:VARCHAR(20)
和CHAR(20)
。接下来插入一些尾部有5个空格的数据,并观察它们的存储情况。
CREATE TABLE strings(id INT PRIMARY KEY AUTO_INCREMENT,variable VARCHAR(20),fixed CHAR(20)
);INSERT INTO strings (variable, fixed) VALUES ("Drifter ", "Drifter ");
如果运行以下SELECT
语句,表面上看返回的数据是相同的:
SELECT * FROM strings;
但如果使用CHAR_LENGTH
函数来计算每个字段实际使用的字符数,就会发现差异。VARCHAR
字段(用varchar_data_length
表示)显示为12,其中包括结尾的5个空格字符,而CHAR
字段仅显示为7。
这是因为MySQL存储了VARCHAR
值末尾的空格,但认为CHAR
值的末尾空格只是填充,因此忽略了这一部分数据。
SELECT CHAR_LENGTH(variable) AS varchar_data_length, CHAR_LENGTH(fixed) AS char_data_length FROM strings;
字段存储空间示例
当数据写入磁盘时,VARCHAR
值会有额外的开销。如果存储字符串 “Spider”(长度为6个字符)到VARCHAR(6)
和CHAR(6)
的字段中,以utf8mb4
字符集为例,以下是磁盘空间消耗情况:
VARCHAR
值占用25字节(每字符4字节 + 1字节开销)。CHAR
值占用24字节(每字符4字节,无额外开销)。
如果存储字符串 “Eido” 到这些字段,以下结果会发生变化:
VARCHAR
只使用17字节,因为它是可变长度。CHAR
保持使用24字节,因为它是固定长度且右填充了2个空格。
字段存储对照表如下:
值 | VARCHAR(6) 存储值 | VARCHAR(6) 使用空间 | CHAR(6) 存储值 | CHAR(6) 使用空间 |
---|---|---|---|---|
“Spider” | “Spider” | 25 字节 | “Spider” | 24 字节 |
“Eido” | “Eido” | 17 字节 | "Eido " | 24 字节 |
"Eido " | "Eido " | 25 字节 | "Eido " | 24 字节 |
小结
最后,总结一下本文的关键点:
- VARCHAR特点:可变长度,适用于存储长度不固定的字符串,并且根据实际数据长度动态分配空间。
- CHAR特点:固定长度,有性能优势,但可能导致存储空间浪费,适用于长度固定的字符串。
- 字符集影响:字符集决定了每个字符的字节数,以及存储时所需的空间大小,如utf8mb4需要1~4字节。
- 数据存储差异:VARCHAR保留尾部空格且会增加长度指示字节,CHAR填充尾部空格但在查询时忽略。
- 空间消耗对比:VARCHAR更节省空间,但有附加开销;CHAR采用固定空间,适合少量数据且不受字符长度变化影响。
在数据库设计中,VARCHAR和CHAR是两种常见的字符串存储类型,它们各有适用场景和性能特点。在选择字段类型时,应充分考虑数据的变化形态、存储性能和空间效率。