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

VARCHARTEXT有什么区别?

#1 楼

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)TINYTEXT,并且如果有人尝试将所有三本《指环王》书籍的文本保存在您的电话号码栏中,则您只存储前30个字符:)

编辑:如果要存储在数据库中的文本长于65535个字符,则必须选择TEXTMEDIUMTEXT,但要小心:LONGTEXT存储的字符串最多16 MB,MEDIUMTEXT最多4 GB。如果使用LONGTEXT并通过PHP获取数据(至少如果使用不带LONGTEXTmysqli),则可能会遇到内存分配错误,因为PHP尝试分配4 GB内存以确保可以缓冲整个字符串。除了PHP以外,其他语言也可能发生这种情况。

但是,在将输入存储到数据库之前,应始终检查输入(是否太长?它是否包含奇怪的代码?)。
注意:对于这两种类型,所需的磁盘空间仅取决于存储的字符串的长度,而不取决于最大长度。如果使用字符集latin1并将文本“ Test”存储在store_resultVARCHAR(30)VARCHAR(100)中,则始终需要5个字节(1个字节存储字符串的长度,每个字符1个字节)。如果将相同的文本存储在TINYTEXTVARCHAR(2000)列中,则也将需要相同的空间,但是在这种情况下,它将是6个字节(2个字节用于存储字符串长度,每个字符1个字节)。 br />
有关更多信息,请参阅文档。

最后,我想添加一个通知,TEXTTEXT都是可变长度数据类型,因此它们可能会最小化存储数据所需的空间。但这需要权衡性能。如果需要更好的性能,则必须使用固定长度类型,例如VARCHAR。您可以在此处了解更多信息。

评论


@AbcAeffchen我相信我明白了你的意思。基本上,“固定最大尺寸”意味着您根本无法设置尺寸-即使您不想支持这么大的尺寸,也始终为65535。这意味着TEXT是VARCHAR字段的简写形式,最大大小为2 1 -1,而忽略了索引问题。我明白吗?

– DemiImp
17年1月2日在8:47

@DemiImp正确。我认为这是我在前两行中写的。我将在您的解释中添加注释。

– AbcAeffchen
17年1月2日在8:55

TEXT比VARCHAR有什么优势?

–所罗门·乌科(Solomon Ucko)
18年7月22日在20:34

看看这个答案,并注意评论。

– AbcAeffchen
18年7月22日在20:52

不可以,固定长度CHAR不会提供任何明显的性能改进。 (这来自一个关于MyISAM表的老太太的故事;即使在那儿,它的有效性也令人怀疑。)

–里克·詹姆斯(Rick James)
19年1月27日在23:39

#2 楼

上面的答案中有一个重要的细节已被忽略。

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

还要注意实际VARCHAR字段所需的字节数取决于列(和内容)的编码。 MySQL会计算用于最大行大小的最大可能字节,因此,如果使用VARCHAR之类的多字节编码(几乎可以肯定),它将用尽最大行大小。

纠正注意:无论MySQL如何计算最大行大小,utf8mb4 / VARCHAR字段数据是实际存储在行中还是通过引用存储都取决于您的基础存储引擎。对于InnoDB,行格式会影响此行为。 (感谢Bill-Karwin)

使用TEXT的原因:如果要存储一段或更多文本,请使用

t需要为列建立索引
如果您已达到表的行大小限制

使用TEXT的原因:存储一些单词或句子
如果要为(entire)列建立索引
如果要使用具有外键约束的列


评论


不,默认情况下,VARCHAR和TEXT都将其部分内容存储在行中。如果表的ROW_FORMAT = DYNAMIC并且内容不适合行,则VARCHAR或TEXT都将存储为指向另一页的指针。

– Bill Karwin
20-2-19在23:56

同样,有关utf8mb4占用更多字节的声明也不准确。仅当您的内容实际上需要多字节字符时,这些单个字符才会占用2、3或4个字节。 utf8中更常见的字符仍然每个字符占用1个字节。这就是utf8的重点!

– Bill Karwin
20-2-19在23:57

如果ROW_FORMAT = COMPACT,则VARCHAR和TEXT都将在行中存储其前768个字节,其余存储在另一页上。

– Bill Karwin
20-2-20在0:01

MySQL手册指出“ ...即使存储引擎能够支持更大的行。BLOB和TEXT列仅对行大小限制贡献9到12个字节,因为它们的内容与其余行分开存储。”如果它在与手册相矛盾的行中存储了该内容的一部分。 @比尔·卡文

–代码指挥官
20-2-20在17:08



是的+1。仅供参考,在64KB限制和InnoDB行大小限制之间的怪异差异是由于MySQL的存储引擎体系结构引起的。当行从存储引擎转移到SQL层,然后变成结果集时,它们必须满足不同的规则。

– Bill Karwin
20-2-20在17:40