在 MySQL 中,索引前缀长度为什么选择为 191
在 MySQL 中,索引前缀长度选择为 191 的常见原因主要与 字符集编码 和 索引长度限制 相关,具体解释如下:
1. 字符集编码的影响
utf8mb4
字符集:- MySQL 的
utf8mb4
字符集每个字符最多占用 4 个字节(相比utf8
的 3 字节,utf8mb4
支持完整的 Unicode 字符,包括表情符号)。 - 如果索引字段使用
utf8mb4
编码,索引的长度限制会以字节为单位计算。
- MySQL 的
- 索引长度限制:
- 在 MySQL 的 InnoDB 存储引擎中,默认情况下单个索引的最大长度为 767 字节(对于
COMPACT
或REDUNDANT
行格式)。 - 因此,当使用
utf8mb4
编码时,767 字节 ÷ 4 字节/字符 ≈ 191 字符。
- 在 MySQL 的 InnoDB 存储引擎中,默认情况下单个索引的最大长度为 767 字节(对于
2. 为什么是 191 而不是其他数值?
- 平衡性能与存储:
- 如果索引前缀长度过短(如 50 或 100),可能会导致索引的选择性(即唯一值的比例)降低,从而影响查询性能。
- 如果前缀长度过长(如 255),可能会超出索引的长度限制,导致索引创建失败或性能下降。
- 191 是一个折中的选择,既能覆盖大部分查询需求,又不会超出索引的长度限制。
- 历史原因:
- 在 MySQL 5.5 及更早版本中,
utf8mb4
尚未普及,utf8
编码每个字符占用 3 字节,因此索引长度限制为 767 字节 ÷ 3 ≈ 255 字符。 - 随着
utf8mb4
的普及,191 字符成为新的标准选择。
- 在 MySQL 5.5 及更早版本中,
3. 示例说明
假设有一个表 users
,其中有一个 email
字段,类型为 VARCHAR(255)
,并使用 utf8mb4
编码:
CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,email VARCHAR(255) NOT NULL,KEY `email_index` (`email`(191)) USING BTREE
);
索引长度计算:email
字段最多 255 字符,使用utf8mb4
编码时,每个字符最多 4 字节。- 索引前缀长度为 191,因此索引占用的最大字节数为 191 × 4 = 764 字节,小于 InnoDB 的默认索引长度限制 767 字节。
- 查询性能:
- 如果查询条件是
WHERE email LIKE 'example%'
,索引前缀email(191)
可以有效加速查询。 - 如果前缀长度过短(如 50),可能会导致索引的选择性降低,查询性能下降。
- 如果查询条件是
4. 特殊情况
- 启用
innodb_large_prefix
:- 在 MySQL 5.7.7 及以上版本中,默认启用了
innodb_large_prefix
,允许单个索引的最大长度增加到 3072 字节。 - 在这种情况下,可以选择更长的前缀长度(如 255 字符),但需要权衡存储和性能。
- 在 MySQL 5.7.7 及以上版本中,默认启用了
- 其他存储引擎:
- MyISAM 存储引擎的索引长度限制为 1000 字节,因此对于
utf8mb4
编码,前缀长度可以达到 1000 ÷ 4 = 250 字符。
- MyISAM 存储引擎的索引长度限制为 1000 字节,因此对于
5. 总结
- 191 是默认选择:
- 在 InnoDB 存储引擎中,使用
utf8mb4
编码时,767 字节的索引长度限制导致前缀长度为 191 字符。 - 这是一个平衡性能和存储的合理选择。
- 在 InnoDB 存储引擎中,使用
- 根据需求调整:
- 如果查询条件需要更高的选择性,可以增加前缀长度(如 255),但需要确保不超过索引长度限制。
- 如果存储空间有限,可以减少前缀长度(如 100),但可能会影响查询性能。
- 版本和配置的影响:
- 在 MySQL 5.7.7 及以上版本中,启用
innodb_large_prefix
后,可以选择更长的前缀长度。
- 在 MySQL 5.7.7 及以上版本中,启用
通过合理选择索引前缀长度,可以在保证查询性能的同时,优化存储空间的使用。