【发布时间】:2014-10-07 16:16:35
【问题描述】:
当我们在 MySQL 中创建一个带有 VARCHAR 列的表时,我们必须为其设置长度。但是对于TEXT 类型,我们不必提供长度。
VARCHAR 和TEXT 有什么区别?
【问题讨论】:
当我们在 MySQL 中创建一个带有 VARCHAR 列的表时,我们必须为其设置长度。但是对于TEXT 类型,我们不必提供长度。
VARCHAR 和TEXT 有什么区别?
【问题讨论】:
上面的答案中省略了一个重要的细节。
MySQL 对max size of each row 施加了 65,535 个字节的限制。
VARCHAR 列的大小计入最大行大小,而TEXT 列假定通过引用存储其数据,因此它们只需要 9-12 个字节。这意味着即使您的 VARCHAR 字段的“理论”最大大小为 65,535 个字符,如果您的表中有多个列,您也无法实现。
另请注意,VARCHAR 字段所需的实际字节数取决于列(和内容)的编码。 MySQL 将可能使用的最大字节数计入最大行大小,因此如果您使用像 utf8mb4 (which you almost certainly should) 这样的多字节编码,它将占用更多的最大行大小。
更正:无论 MySQL 如何计算最大行大小,VARCHAR/TEXT 字段数据是实际存储在行中还是通过引用存储取决于您的底层存储引擎。对于 InnoDB,row format 会影响此行为。 (感谢比尔-卡尔文)
使用TEXT的原因:
使用VARCHAR的原因:
【讨论】:
TEXT
c 字节的磁盘空间,其中 c 是存储字符串的长度。VARCHAR(M)
M 个字符的可变最大大小M 需要介于 1 和 65535 之间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 的文档)。
但您也想使用VARCHAR,如果您知道可能输入字符串的最大长度仅为M,例如电话号码或姓名或类似的东西。然后您可以使用VARCHAR(30) 而不是TINYTEXT 或TEXT,如果有人试图将所有三本“指环王”书籍的文本保存在您的电话号码列中,您只存储前 30 个字符:)
编辑:如果要存储在数据库中的文本长度超过 65535 个字符,则必须选择 MEDIUMTEXT 或 LONGTEXT,但要小心:MEDIUMTEXT 存储字符串向上最大 16 MB,LONGTEXT 最大 4 GB。如果您使用LONGTEXT 并通过PHP 获取数据(至少如果您使用mysqli 而不使用store_result),您可能会遇到内存分配错误,因为PHP 尝试分配4 GB 的内存以确保整个字符串可以缓冲。这可能也发生在 PHP 以外的其他语言中。
但是,您应该始终检查输入(是否太长?是否包含奇怪的代码?)在将其存储到数据库之前。
注意:对于这两种类型,所需的磁盘空间仅取决于存储字符串的长度,而不取决于最大长度。
例如如果您使用字符集 latin1 并存储文本VARCHAR(30)、VARCHAR(100)和TINYTEXT中的“测试”,它总是需要5个字节(1个字节存储字符串的长度,每个字符1个字节)。如果您将相同的文本存储在 VARCHAR(2000) 或 TEXT 列中,它也需要相同的空间,但在这种情况下,它将是 6 个字节(2 个字节用于存储字符串长度,每个 1 个字节字符)。
有关更多信息,请查看documentation。
最后,我想补充一点,TEXT 和 VARCHAR 都是可变长度数据类型,因此它们很可能会最大限度地减少存储数据所需的空间。但这伴随着性能的权衡。如果你需要更好的性能,你必须使用像CHAR这样的固定长度类型。你可以阅读更多关于这个here的信息。
【讨论】:
TEXT 比 VARCHAR 有什么优势?
CHAR 没有提供任何明显的性能改进。 (这来自一个关于 MyISAM 表的老妇人故事;即使在那里它的有效性也值得怀疑。)
TEXT 不能有默认值,而VARCHAR 可以。见Why can't a text column have a default value in MySQL? - Stack Overflow