【问题标题】:Difference between VARCHAR and TEXT in MySQL [duplicate]MySQL中VARCHAR和TEXT之间的区别[重复]
【发布时间】:2014-10-07 16:16:35
【问题描述】:

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

VARCHARTEXT 有什么区别?

【问题讨论】:

    标签: mysql text varchar


    【解决方案1】:

    上面的答案中省略了一个重要的细节。

    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的原因:

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

    【讨论】:

    • 否,VARCHAR 和 TEXT 默认将部分内容存储在行中。如果表的 ROW_FORMAT=DYNAMIC 并且内容不适合该行,则 VARCHAR 或 TEXT 都将存储为指向另一个页面的指针。
    • 另外关于 utf8mb4 占用更多字节的说法也不准确。只有当您的内容确实需要多字节字符时,这些单独的字符才会占用 2、3 或 4 个字节。 utf8 中更常见的字符仍然占用每个字符 1 个字节。这就是 utf8 的重点!
    • 如果 ROW_FORMAT=COMPACT,那么 VARCHAR 和 TEXT 都会将它们的前 768 个字节与行一起存储,其余的将存储在另一个页面上。
    • 我已经更新了我的答案以澄清这些细节。现在看起来准确吗? @BillKarwin
    • 是的! +1。仅供参考,64KB 限制和 InnoDB 行大小限制之间的这种奇怪差异是由于 MySQL 的存储引擎架构造成的。由于行从存储引擎传输到 SQL 层,然后制成结果集,它们必须满足不同的规则。
    【解决方案2】:

    TL;DR

    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 的文档)。

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

    编辑:如果要存储在数据库中的文本长度超过 65535 个字符,则必须选择 MEDIUMTEXTLONGTEXT,但要小心: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

    最后,我想补充一点,TEXTVARCHAR 都是可变长度数据类型,因此它们很可能会最大限度地减少存储数据所需的空间。但这伴随着性能的权衡。如果你需要更好的性能,你必须使用像CHAR这样的固定长度类型。你可以阅读更多关于这个here的信息。

    【讨论】:

    • @AbcAeffchen 我相信我明白了你的意思。基本上,“固定最大尺寸”意味着您根本无法设置尺寸 - 即使您不想支持那么大的尺寸,它也始终为 65535。这意味着 TEXT 是最大大小为 2¹⁶-1 的 VARCHAR 字段的简写,而忽略了索引问题。我没听错吧?
    • TEXTVARCHAR 有什么优势?
    • 不,固定长度CHAR 没有提供任何明显的性能改进。 (这来自一个关于 MyISAM 表的老妇人故事;即使在那里它的有效性也值得怀疑。)
    • 另外,TEXT 不能有默认值,而VARCHAR 可以。见Why can't a text column have a default value in MySQL? - Stack Overflow
    • @SolomonUcko 当您要创建具有两个最大字符串列的表时,您需要使用 TEXT,这意味着它们可能都需要 65535 个字符。您不能同时在一行中使用两个最大大小的 varchar,因为 MySQL 限制了最大行大小,即 65535。但是您可以在一行中使用两个 TEXT,因为 TEXT 仅对行大小限制贡献 9 到 12 个字节, TEXT 的内容与行的其余部分分开存储。
    猜你喜欢
    • 2011-04-22
    • 2012-02-23
    • 2012-12-18
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    • 2016-09-17
    • 2016-05-31
    • 1970-01-01
    相关资源
    最近更新 更多