我有一个contacts表,其中包含postcodefirst namelast nametowncountryphone number等字段,所有这些字段都被定义为VARCHAR(255),尽管这些字段都不会接近255个字符.(如果你想知道的话,这是因为Ruby on Rails迁移默认情况下会将字符串字段映射到VARCHAR(255),我从来没有想过要覆盖它).

由于VARCHAR只存储字段的实际字符数(以及字段长度),使用VARCHAR(16)VARCHAR(255)有什么明显的优势(性能或其他方面)?

此外,大多数字段都有索引.字段上较大的VARCHAR大小是否会影响索引的大小或性能?

仅供参考,我使用的是MySQL 5.

推荐答案

在存储器中,VARCHAR(255)足够智能,可以只存储给定行上所需的长度,而CHAR(255)总是存储255个字符.

但是,既然您用MySQL标记了这个问题,我将提到一个MySQL特有的技巧:当行从存储引擎层复制到SQL层时,VARCHAR个字段将转换为CHAR,以获得使用固定宽度行的优势.因此,内存中的字符串变成了声明的VARCHAR列中的padded out to the maximum length个.

当查询隐式生成临时表时,例如在排序或GROUP BY时,这可能会占用大量内存.如果对不需要那么长的数据使用大量VARCHAR(255)个字段,这会使临时表非常大.

您可能还想知道,这种"填充"行为意味着使用utf8字符集声明的字符串将每个字符填充到三个字节,即使对于存储为单字节内容的字符串(例如ascii或拉丁字符).同样地,utf8mb4字符集会使字符串在内存中的每个字符填充到四个字节.

因此,一个VARCHAR(255)英寸的utf8存储一个短字符串,比如"No opinion",在磁盘上需要11个字节(10个较低的字符集字符,加上一个字节的长度),但在内存中需要765个字节,因此在临时表或排序结果中也需要765个字节.

我帮助过MySQL用户,他们在不知不觉中频繁创建了1.5GB临时表,并填满了他们的磁盘空间.它们有很多VARCHAR(255)列,实际上存储的是非常短的字符串.

最好根据要存储的数据类型定义列.正如其他人所提到的,强制实施与应用程序相关的约束是有好处的.但它有物理上的好处,可以避免我上面描述的内存浪费.

当然,很难知道最长的邮政地址是什么,这就是为什么许多人 Select 了比任何地址都长的长VARCHAR.255是常用的,因为它是VARCHAR的最大长度,长度可以用一个字节编码.它也是MySQL中超过5.0的最大VARCHAR长度.

Mysql相关问答推荐

我可以在插件中访问SQL密钥对吗?

SQL计算不同的列并返回所有行

用于搜索从各种表中获得的结果的查询

Mysql:使用like Select 查询

docker-compose:无法将应用程序服务连接到 mysql 数据库,收到错误:用户‘root’@‘localhost’访问被拒绝(使用密码:YES)

如何计算具有权重属性的记录数

过滤值为0时如何在MySQL查询中设置条件?

仅计算 DATEDIFF (MySQL) 中的工作日

如何使用 DBD::mysql 判断 MySQL 服务是否正在运行

将sql查询转换为sequelize

带有 PARTITION BY 子句的 ROW_NUMBER() 停止在 MariaDB 上工作

MYSQL REGEXP_REPLACE 在数字之后

基于 3 个条件 Select 3 行的最佳 MySQL 索引和查询

在 WHERE 子句中使用 CASE

是否可以在内部连接期间重命名连接列?

字符ي和ی以及波斯语的区别 - Mysql

错误:无法构建 gem 本机扩展(rails 3.2.3 上的 mysql2)

将 JavaScript 到日期对象转换为 MySQL 日期格式 (YYYY-MM-DD)

应该使用什么列类型将序列化数据存储在 mysql 数据库中?

int(11) 和 int(11) UNSIGNED 有什么区别?