前缀索引能减少b+树层级,因截取字符串前缀后键值变小,每页可存更多键值、扇出增大,同等数据量下树高降低(如从4层压至2–3层),从而减少磁盘i/o;但前缀过短会降低区分度导致回表行数增多,过长则失去优化意义。

前缀索引为什么能减少B+树层级
因为TEXT或长VARCHAR字段全量建索引时,单个索引项过大,导致B+树每个节点能容纳的键值数量急剧下降,树高被迫增加——每多一层,就多一次磁盘IO。前缀索引把content(255)这种长度限制住,让键值变小,节点密度回升,树高通常能从4层压到2–3层。
前缀长度不是越长越好
选错前缀长度反而会放大IO压力:过短(如content(10))导致大量前缀重复,索引区分度低,查出来一堆候选行,最终仍要回表逐行比对;过长(如content(1000))又逼近全字段大小,B+树优化失效。实操建议:
- 用
SELECT COUNT(DISTINCT LEFT(content, N)) / COUNT(*) FROM table算区分度,目标>0.95 - 结合业务场景:URL字段通常
LEFT(url, 128)就够,JSON日志可能需要LEFT(log, 512) - 避免在WHERE中用函数包裹前缀列,比如
WHERE UPPER(content) LIKE 'ABC%'会让索引失效
前缀索引无法解决ORDER BY大字段问题
这是最容易被混淆的一点:前缀索引只加速WHERE和JOIN中的等值/范围查找,对ORDER BY content完全无效。MySQL 5.7要求排序必须比对完整字段值,而前缀索引不存储剩余部分,优化器直接放弃使用索引排序,强制触发filesort。即使EXPLAIN显示key用了索引,Extra里仍会出现Using filesort。
真正降低IO的关键是避免回表
前缀索引的价值常被误读为“减小索引体积”,其实核心在于配合覆盖索引减少IO次数:
- 如果查询只需
SELECT id, title FROM posts WHERE content LIKE 'xxx%',且title也在联合索引里,就能走覆盖索引,不用回主键聚簇索引查数据 - 但若查
SELECT *或包含未索引字段,前缀索引本身不改变回表成本,只是让定位更准、回表行数更少 - 注意
LIKE 'xxx%'能用前缀索引,LIKE '%xxx'则完全不能











