MySQL中VARCHAR和TEXT的区别

当我们在MySQL中创建一个带有VARCHAR列的表时,我们必须为它设置长度。但是对于TEXT类型,我们不需要提供长度。

VARCHARTEXT之间有什么区别?

409046 次浏览

博士TL;

TEXT

  • 固定最大大小为65535字符(你不能限制最大大小)
  • 占用2 + c字节的磁盘空间,其中c是存储字符串的长度。
  • 不能(完全)成为索引的一部分。我们需要指定一个前缀长度。

VARCHAR(M)

  • M字符的可变最大大小
  • M需要在1到65535之间
  • 占用1 + c字节(用于M ≤255)或2 + c(用于256 ≤M勒;65535)字节的磁盘空间,其中c是存储字符串的长度
  • 可以成为索引的一部分吗

更多的细节

TEXT固定最大大小为2¹⁶-1 = 65535个字符 VARCHAR具有变量最大大小M M = 2¹⁶-1.
所以你不能选择TEXT的大小,但你可以选择VARCHAR.

另一个区别是,你不能在TEXT列上放置索引(全文索引除外) 所以如果你想在列上有一个索引,你必须使用VARCHAR。但是请注意,索引的长度也是有限的,所以如果你的VARCHAR列太长,你必须在你的索引中只使用VARCHAR列的前几个字符(参见CREATE INDEX的文档)

但如果你知道可能的输入字符串的最大长度只有M,例如一个电话号码或一个名字或类似的东西,你也想使用VARCHAR。然后你可以使用VARCHAR(30)而不是TINYTEXTTEXT,如果有人试图在你的电话号码列中保存所有三本“指环王”书籍的文本,你只存储前30个字符:)

编辑:如果你想在数据库中存储的文本长度超过65535个字符,你必须选择MEDIUMTEXTLONGTEXT,但要小心:MEDIUMTEXT存储最多16mb的字符串,LONGTEXT存储最多4gb的字符串。如果你使用LONGTEXT并通过PHP获取数据(至少如果你使用mysqli而没有store_result),你可能会得到一个内存分配错误,因为PHP试图分配4gb内存以确保整个字符串可以被缓冲。在PHP以外的其他语言中也可能发生这种情况。

然而,你应该总是检查输入(是不是太长了?是否包含奇怪的代码?)之前将其存储在数据库中。

注意:对于这两种类型,所需的磁盘空间仅取决于存储字符串的长度,而不取决于最大长度 例如如果你使用字符集latin1并将文本“Test”存储在VARCHAR(30)VARCHAR(100)TINYTEXT中,它总是需要5个字节(1个字节存储字符串长度,1个字节存储每个字符)。如果你在VARCHAR(2000)TEXT列中存储相同的文本,它也需要相同的空间,但是,在这种情况下,它将是6个字节(2个字节存储字符串长度,1个字节存储每个字符)。

有关更多信息,请查看文档

最后,我想补充一个注意事项,TEXTVARCHAR都是变长数据类型,因此它们很可能最小化存储数据所需的空间。但这需要性能的权衡。如果你需要更好的性能,你必须使用像CHAR这样的固定长度类型。你可以阅读更多关于在这里

在上面的回答中有一个重要的细节被忽略了。

MySQL对每一行的最大大小的限制为65,535字节。 VARCHAR列的大小被计算为最大行大小,而TEXT列被假设通过引用存储它们的数据,因此它们只需要9-12字节。这意味着即使你的VARCHAR字段的“理论”最大大小是65,535个字符,如果你的表中有多个列,你将无法实现这一点

还要注意,VARCHAR字段所需的实际字节数取决于列(和内容)的编码。MySQL将最大可能使用的字节数计算为最大行大小,因此如果您使用像utf8mb4 (你几乎肯定应该这么做)这样的多字节编码,它将使用更多的最大行大小。

更正:不管MySQL如何计算最大行大小,VARCHAR/TEXT字段数据是否实际存储在行中或通过引用存储取决于您的底层存储引擎。对于InnoDB, 行格式会影响这种行为。(感谢Bill-Karwin)

使用TEXT的原因:

  • 如果您想存储一段或更多文本
  • 如果您不需要索引该列
  • 如果已达到表的行大小限制

使用VARCHAR的原因:

  • 如果你想储存几个单词或一个句子
  • 如果您想索引(整个)列
  • 如果要使用带有外键约束的列