VARCHAR和CHAR有什么区别?

443

VARCHAR和CHAR在MySQL中有什么区别?

我正在尝试存储MD5哈希值。


17
MD5哈希始终为32个字符。因此,为了最大化性能,请使用CHAR(32),因为CHAR是固定长度的(有关CHAR和VARCHAR之间差异的更多细节,请参见以下答案)。 - Augustin
MySQL文档:CHAR和VARCHAR类型 - rinogo
17个回答

433

VARCHAR是可变长度的。

CHAR是固定长度的。

如果您的内容是固定大小的,使用CHAR将获得更好的性能。

请参阅MySQL关于CHAR和VARCHAR类型的页面以获取详细的解释(一定要阅读评论)。


68
@steven: 当 Anon. 说“你的内容是固定大小”时,意思是表格中的行必须包含所有固定大小的字段。如果你在一个字段中使用 CHAR 而不是 VARCHAR,但表格包含其他字段是 VARCHAR,那么你不会获得性能提升。 - Marco Demaio
2
没有char数据类型会增加性能...在执行查询时,SQL将生成执行计划。假设有2个列charcol char(2000)和VarcharCol Varchar(2000)。在执行计划中,varchar类型的列的估计行大小可能被低估。因此,它会导致溢出到temp db。因此,使用char对于性能是有好处的。 - vignesh
1
VARCHAR(n)中括号中的值是什么意思? - Sivagami Nambi
@Marco Demaio,你知道这背后的原因吗? - Dehan
1
@jdc91:为了提高性能,整行必须是固定宽度。MySQL在计算这种类型表格的空间需求和行偏移量时会获得优势。 - Marco Demaio
虽然我认为这是真实的,但重要的是要指出,在连接过程中,varchar将会扩展到最大长度,并占用相应的内存空间。 - theking2

258

CHAR

  1. 用于存储固定长度的字符字符串值。
  2. 数据类型可以容纳的最大字符数为255个字符
  3. 比VARCHAR快50%
  4. 使用静态内存分配

VARCHAR

  1. 用于存储可变长度的字母数字数据。
  2. 此数据类型可以容纳的最大字符数为:
    • MySQL 5.0.3之前:255个字符
    • MySQL 5.0.3之后:65,535个字符,共用于行。
  3. 比CHAR慢。
  4. 使用动态内存分配

3
我有些惊讶这个答案被频繁点赞。MySQL文档中指出,“VARCHAR列中的值是可变长度的字符串。在MySQL 5.0.3之前,长度可以指定为0到255的值,在5.0.3及以后的版本中,长度可以指定为0到65,535。” - DroidOS
3
更不用说你还可以在char中存储字母数字数据。 - ninjabber
70
这个“50%更快”是基于什么?相对于什么来说更快了50%?在什么条件下?此外,静态内存分配和动态内存分配在这个语境中是什么意思? - Martin Smith
10
@MartinSmith,我本来也想问同样的问题... 不认为那个信息是准确的。https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:2668391900346844476 - rasso
5
这里的性能声明含糊且没有证据支持,内存分配策略的差异(以及其重要性)没有详细说明,而varchar存储“字母数字数据”的说法有点奇怪;varchar列肯定也可以存储非字母数字字符! - Mark Amery
显示剩余4条评论

138

CHAR用于固定长度的变量,而VARCHAR用于可变长度的变量。

例如:

Create table temp
(City CHAR(10),
Street VARCHAR(10));

Insert into temp
values('Pune','Oxford');

select length(city), length(street) from temp;

输出结果将是:

length(City)          Length(street)
10                    6

结论:如果变量长度是可变的,为了有效地利用存储空间,必须使用VARCHAR而不是CHAR。


4
城市 = char(10), 街道 = varchar(10), 城市 = Pune, 街道 = Oxford, length(城市) = 4, length(街道) = 6 - abdulwadood
4
在MySQL 5.7中,运行此查询语句(select length(city), length(street) from temp)会得到以下输出: mysql> select length(city), length(street) from temp; +--------------+----------------+ | length(city) | length(street) | +--------------+----------------+ | 4 | 6 | +--------------+----------------+ 1 row in set (0.00 sec) - Jasbeer Rawal

86

CHAR(x) 表示该列只能容纳 恰好 x 个字符。
VARCHAR(x) 表示该列最多可容纳 不超过 x 个字符。

由于 MD5 哈希值始终具有相同的大小,您应该使用 CHAR 类型。

然而,您本来就不应该使用 MD5;它已经被证明存在弱点。
请改用 SHA2。
如果要对密码进行哈希操作,请使用 bcrypt。


52
"A CHAR(x)列只能有恰好x个字符。" 实际上,您可以添加少于x个字符的数据,但我认为您的意思是它始终在幕后保留10个字符的内存空间。 - Dan W
16
他们为什么要存储MD5哈希值,你并不清楚。但是使用MD5的合理原因有很多,这与安全无关。碰撞事件非常罕见,而且该算法比更安全的算法速度更快。 - John Hunt
2
假设CHAR(x)列不强制要求x个字符,即使对于固定大小的数据,是否有使用它而不是VARCHAR(x)的理由? - NeverEndingQueue

12

在MySQL中,VARCHAR和CHAR有什么区别?

对于已经给出的答案,我想补充一点,在OLTP系统或者频繁更新的系统中,建议即使是对于可变尺寸的列,也可以考虑使用CHAR,这是因为更新期间可能会导致VARCHAR列的碎片化。

我正在尝试存储MD5哈希值。

如果确实涉及到安全问题,那么MD5哈希值并不是最好的选择。但是,如果您要使用任何哈希函数,请考虑使用BINARY类型(例如,MD5将生成16字节哈希值,因此BINARY(16)就足够了,而不需要使用32个十六进制数字来表示字符的CHAR(32)。这样可以节省更多的空间,并且效率更高。


按照这个思路,我会在业务 ID 需要可读性而非效率时使用 CHAR。但是我仍然会使用 bigint 作为主键。 - Archimedes Trajano

10

Varchar会在输入的字符长度比声明长度短时切断尾随空格,而char则不会。Char会填充空格,并始终具有声明长度。就效率而言,varchar更为灵活,因为它修剪字符以允许更多调整。然而,如果您知道char的确切长度,char将以稍微更快的速度执行。


9

CHAR是固定长度的,而VARCHAR是可变长度的。每个CHAR输入始终使用相同的存储空间,而VARCHAR仅使用存储实际文本所需的空间。


9

CHAR是固定长度字段;VARCHAR是可变长度字段。如果您要存储长度差异很大的字符串,比如姓名,那么请使用VARCHAR,如果长度始终相同,则使用CHAR,因为它稍微更节省空间,并且速度稍微更快。


虽然我猜这里关于速度和存储效率的说法是正确的,但它们都没有得到任何证实(而且很可能是错误的),这使得这个答案毫无用处;它只是重复了读者可能已经预期为真实的内容,而没有做任何真正有助于确认的事情。 - Mark Amery

9
在大多数关系型数据库管理系统中,它们是同义词。但是对于那些仍有区别的系统来说,CHAR字段被存储为固定宽度的列。如果您将其定义为CHAR(10),则会将10个字符写入表格,其中“填充”(通常为空格)用于填充数据未使用的任何空间。例如,保存“bob”将保存为(“bob”+7个空格)。VARCHAR(可变字符)列旨在存储数据,而不浪费CHAR列的额外空间。
与往常一样,维基百科 说得更清楚。

我不同意“它们是同义词”的说法。例如MySQL似乎直接反驳了这个说法。 "CHAR和VARCHAR类型相似,但在存储和检索方式上有所不同..." (来源) - rinogo
1
"在大多数情况下"......而"今天"已经是12年前了 :) - Greg Fenton
你是对的!更新答案可能对其他人有价值。 - rinogo

6

CHAR

  1. 使用特定的内存分配方式
  2. 时间高效

VARCHAR

  1. 使用动态内存分配方式
  2. 内存高效

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接