10

我看到评论“如果您在 varchar(20) 列中有 10 到 15 个字符之间的 5000 万个值,并且在 varchar(50) 列中有相同的 5000 万个值,它们将占用完全相同的空间。这就是重点varchar,而不是 char。”。谁能告诉我原因?请参阅人员“姓名”字段的合理长度限制是多少?

4

3 回答 3

9

MySQL 提供了多种存储引擎选择。数据的物理存储取决于存储引擎。

VARCHAR 的 MyISAM 存储

在 MyISAM 中,VARCHARs 通常只占用字符串的实际长度加上一两个字节的长度。这是因为 MyISAM 的设计限制为表锁定而不是行锁定功能。性能后果包括更紧凑的缓存配置文件,但也更复杂(更慢)的记录偏移计算。

(事实上​​,MyISAM 为您在固定物理行大小和可变物理行大小表格式之间提供了一定程度的选择,具体取决于整个表中出现的列类型。发生的VARCHAR更改仅默认方法,但TEXTblob的存在迫使 VARCHARs同一个表也可以使用可变长度方法。)

物理存储方法对于索引尤其重要,这与表不同。MyISAM 对和列 使用空间压缩,这意味着在这两种情况下,较短的数据在索引中占用的空间较少。CHARVARCHAR

VARCHAR 的 InnoDB 存储

InnoDB 与大多数其他当前关系数据库一样,使用更复杂的机制。 VARCHAR最大宽度小于 768 字节的列将被内联存储,保留的空间与该最大宽度匹配。更准确地说

对于每个非 NULL 可变长度字段,记录头包含一个或两个字节的列长度。仅当列的一部分存储在溢出页的外部或最大长度超过 255 字节且实际长度超过 127 字节时才需要两个字节。对于外部存储的列,两字节长度表示内部存储部分的长度加上指向外部存储部分的 20 字节指针。内部部分为768字节,所以长度为768+20。20 字节指针存储列的真实长度。

InnoDB 目前不在其索引中进行空间压缩,与上述 MyISAM 正好相反。

回到问题

然而,以上所有只是一个实现细节,甚至可能在版本之间发生变化。CHAR和之间的真正区别VARCHAR是语义上的,而 和之间的区别VARCHAR(20)也是如此VARCHAR(50)。通过确保无法在 a 中存储 30 个字符的字符串VARCHAR(20),该数据库使各种处理器和应用程序的生活变得更轻松,更好地定义了它应该集成到可预测行为解决方案中的各种处理器和应用程序。这是大问题。

具体到个人姓名,这个问题可能会给你一些实用的指导。无论如何,全名超过 70 个 UTF-8 字符的人都会遇到麻烦。

于 2012-06-21T07:41:53.780 回答
4

是的,这确实是 VARCHAR 的重点。它只占用与文本长度一样多的空间。

如果你有 CHAR(50),无论数据有多短(它会被填充,通常是空格),它都会占用 50 个字节(或字符)。

谁能告诉我原因?

因为人们认为存储大量无用的填充很浪费,所以他们发明了 VARCHAR。

于 2012-06-21T06:03:03.967 回答
2

手册指出:

CHAR 和 VARCHAR 类型的声明长度表示要存储的最大字符数。(...)

与 CHAR 相比,VARCHAR 值存储为一个字节或两个字节长度的前缀加上数据。长度前缀表示值中的字节数。如果值需要不超过 255 个字节,则一列使用一个长度字节,如果值可能需要超过 255 个字节,则使用两个长度字节。

请注意,VARCHAR(255)VARCHAR(256) 不同。

这是理论。正如 habeebperwad 建议的那样,一行的实际占用空间取决于(引擎)页面大小和(硬盘)块大小。

于 2012-06-21T07:21:38.593 回答