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

Der*_*ney 21 mysql database-design datatypes

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

我正在阅读差异列表,只有两个值得注意的是:

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

BLOB 和 TEXT 列不能有 DEFAULT 值。

那么,由于 TEXT 数据类型的这两个限制,为什么要在 varchar(65535) 上使用它?两者之间是否存在性能影响?

Joe*_*Joe 14

分开链接到一些解释基本问题的信息(存在性能差异),但要说一个总是比另一个更好还不够简单。(否则,就没有理由同时拥有两者。)此外,在 MyISM 中,VARCHAR 的 64k 最大大小不是每个字段——而是每个记录。

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

  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 并且具有固定长度,则记录头没有可变长度部分。
  • 对于每个非 NULL 可变长度字段,记录头包含一或两个字节的列长度。仅当列的一部分存储在溢出页中或最大长度超过 255 字节且实际长度超过 127 字节时,才需要两个字节。对于外部存储的列,两字节长度表示内部存储部分的长度加上指向外部存储部分的 20 字节指针。内部部分是768字节,所以长度是768+20。20 字节的指针存储列的真实长度。

...

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