电话
400 9058 355
前缀索引适用于字段值长且前缀选择性高(≥0.95)的场景,可显著减小索引体积;但不支持完整等值匹配、排序及后缀模糊查询;需避免长度过短、过长或字节截断问题,优先考虑哈希列、生成列等替代方案。
当 VARCHAR 字段(如邮箱、URL、标题)长度动辄 200+,但实际前 10–30 个字符就足以唯一或高度区分时,前缀索引能显著减少索引体积。比如 email 字段平均长度 80,但前 30 位的重复率低于 0.01%,这时建 INDEX idx_email ON users(email(30)) 就比全字段索引节省近 60% 的 B+ 树空间。
关键判断依据不是“字段长”,而是前缀的选择性(COUNT(DISTINCT LEFT(col, N)) / COUNT(*)),建议该值 ≥ 0.95 再考虑前缀索引。
前缀索引只保存和比较前 N 个字符,因此以下操作会失效或退化:
WHERE email = 'a@b.com' —— 无法使用前缀索引做等值精确匹配(除非 N 足够覆盖整个值,但这就失去前缀意义)ORDER BY email DESC —— MySQL 无法用前缀索引完成完整排序,会触发 filesortSELECT email FROM users WHERE email LIKE '%@gmail.com' —— 后缀模糊查,前缀索引完全无效这类场景必须用全文索引、生成列索引,或接受全字段索引的空间成本。
选错前缀长度会导致性能反降或空间浪费:
name(2)):中文姓名前 2 字重复极高,选择性差,索引几乎无效url(255)):接近原字段长度,B+ 树节点变大,单页存的键值变少,树高增加,反而降低查询效率name(10) 可能截断一个 3 字节汉字,导致索引值损坏;应结合 CHAR_LENGTH() 和 LENGTH() 验证实际字节数实操建议:先用 SELECT COUNT(DISTINCT LEFT(url, 32)) / COUNT(*) AS sel FROM pages; 测选择性,再逐步试 32→48→64,直到选择性达标且 SHOW INDEX 中的 Sub_part 列不再明显提升查询命中率。
前缀索引是权衡妥协,不是银弹。遇到长字段索引膨胀,优先检查这些更干净的解法:
ALTER TABLE logs ADD COLUMN url_sha1 CHAR(40) AS (SHA1(url)) STORED;然后对
url_sha1 建普通索引,等值查极快且固定长度ALTER TABLE docs ADD COLUMN title_prefix VARCHAR(50) AS (LEFT(title, 50)) STORED;再建
INDEX idx_title_prefix ON docs(title_prefix)
真正容易被忽略的是:前缀索引无法被 EXPLAIN 中的 key_len 准确反映真实比较逻辑——它只显示定义长度,不体现实际区分效果。线上观察必须结合 Handler_read_key 和慢查中的 rows_examined 综合判

邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...