MySQL VARCHAR和TEXT数据类型有什么区别?


19

在版本5.0.3(允许VARCHAR为65,535字节并停止截断尾随空格)之后,这两种数据类型之间是否有主要区别?

我正在阅读差异列表,注释中仅有的两个是:

对于BLOB和TEXT列上的索引,必须指定索引前缀长度。对于CHAR和VARCHAR,前缀长度是可选的。请参见第7.5.1节“列索引”。

BLOB和TEXT列不能具有DEFAULT值。

因此,由于TEXT数据类型有这两个限制,为什么要在varchar(65535)上使用它?是否有一个相对于另一个的性能影响?


1
当您想要超过65535个字符的数据时?
BlackICE 2011年

下面是关于VARCHAR和文字之间的基准相当不错的论坛主题:http://forums.mysql.com/read.php?24,105964,105964

因为那里的清单确实可以很好地安排明确的细节,并且因为您已经拥有列举的差异清单,所以我不确定这是我们在DBA上需要的问题。是否有一个原因,你所引用的列表中,您提出的理由不是在这种情况下不够好?否则,我要去VtC
jcolebrand

1
我更新了我的问题,但是我不确定一个明显的原因是一个方面的表现。不确定是否还有其他不太明显的原因
Derek Downey

那么,您要问的是一个人的性能特征是否公平?
jcolebrand

Answers:


13

四分五裂链接到一些信息,说明基本问题(有性能差异),但它不是足够简单地说,一个总是优于其他。(否则,没有理由同时拥有两者。)而且,在MyISM中,VARCHAR的最大64k大小不是每个字段而是每个记录。

基本上,有四种方法可以将字符串存储在数据库记录中:

  1. 固定长度
  2. C样式的字符串(在字符串末尾标有NULL或类似的字符)
  3. Pascal样式字符串(一些字节表示长度,然后是字符串)
  4. 指针(将字符串存储在其他位置)

MyISM对VARCHAR使用类似于#3的内容,对TEXT使用一种混合方法,其中将字符串的开头存储在记录中,然后将字符串的其余部分存储在其他地方。InnoDB与VARCHAR类似,但将完整的TEXT字段存储在记录之外。

使用1&4,记录中的内容总是相同的长度,因此,如果您不需要字符串,但需要后面的内容,则跳过该字段会更容易。#2和#3对于短字符串来说都还不错...#2必须继续寻找标记,而#3可以向前跳过...随着字符串变长,#2对于这种特殊用途会变得更糟案件。

如果您实际上需要读取字符串,则#4会比较慢,因为您必须读取记录,然后读取可能存储在磁盘上其他位置的字符串,具体取决于数据库如何处理它。#1总是非常简单明了,并且再次遇到类似的问题,其中字符串越长,#2变得越差,而字符串很小的情况,#3则比#2差,但是随着字符串变长,效果会更好。

然后是存储需求...#1始终是固定长度,因此如果大多数字符串不是最大长度,它可能会膨胀。#2有1个额外的字节;如果最大长度= 255,则#3通常有2个额外的字节,如果最大为64k,则通常有4个额外的字节。#4具有指针长度,通常还有#3的规则。

对于MySQL 5.1中的特定实现,MyISM文档状态为

  • 支持真正的VARCHAR类型;VARCHAR列以存储在一个或两个字节中的长度开头。
  • 具有VARCHAR列的表可能具有固定或动态的行长。
  • 一个表中的VARCHAR和CHAR列的长度总和最大为64KB。

对于InnoDB

  • 记录头的可变长度部分包含一个用于指示NULL列的位向量。如果索引中可以为NULL的列数为N,则位向量占用CEILING(N / 8)个字节。(例如,如果有9到15列可以为NULL的列,则位向量使用两个字节。)NULL列不占用该向量中的位以外的空间。标头的可变长度部分还包含可变长度列的长度。每个长度占用一个或两个字节,具体取决于列的最大长度。如果索引中的所有列都不为空并且具有固定长度,那么记录头将没有可变长度部分。
  • 对于每个非NULL可变长度字段,记录头包含一到两个字节的列长度。仅当部分列存储在外部溢出页面中或最大长度超过255个字节且实际长度超过127个字节时,才需要两个字节。对于外部存储的列,两个字节的长度表示内部存储部分的长度加上指向外部存储部分的20字节指针。内部部分是768个字节,因此长度是768 + 20。20字节的指针存储列的真实长度。

...

与处理数据库时的许多其他事情一样,如果不确定不确定什么最适合您的需求,请尝试使用类似的数据和用法对其进行基准测试,并查看它们的行为。


线程划分了链接状态,表明MySQL内联存储了Blob和文本字段inline forums.mysql.com/read.php?24,105964,267596#msg-267596
Michael

1
Nitpick ...出于所有实际目的,任何一个引擎中的一行都没有64KB的限制。 LONGTEXT并且LONGBLOB是一个很好的例子。C风格的字符串在MySQL(我所知道的)无处使用。InnoDB确实使用“混合”方法,但是它更复杂,具体取决于行大小,row_format等。几乎不建议以“固定”长度存储字符串,除非它们实际上是恒定长度(country_code,zip_code等)。 。InnoDB有4个ROW_FORMATs;文本仅讨论其中的1或2。
瑞克·詹姆斯

2

当SELECT需要创建临时表(例如对结果进行排序)时,它将创建MEMORY表或MyISAM表。内存效率更高。内存有限制-一种是禁止TEXT和BLOB。因此,使用TEXT 的SELECT 运行速度可能比使用VARCHAR慢。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.