多列索引遵循最左前缀原则,仅当查询条件包含最左侧连续列时才生效;其成本取决于索引体积、回表次数和优化器预估精度,是否创建应基于高频查询组合、排序/分组需求及覆盖查询场景。

多列索引不是单列索引的简单叠加,它在查询优化中具有独特的行为和成本特征。是否建多列索引,关键看查询条件的组合模式、列的选择性分布以及排序/分组需求,而非单纯“加更多列更高效”。
多列索引能覆盖哪些查询场景?
多列索引(如 INDEX(a, b, c))遵循最左前缀原则:只有当查询条件包含索引最左侧连续列时,索引才可能被使用。
- 可走索引:WHERE a = ?;WHERE a = ? AND b = ?;WHERE a = ? AND b = ? AND c = ?;WHERE a = ? AND b IN (?, ?) ORDER BY c
- 部分走索引:WHERE a = ? AND c = ?(b缺失,c无法利用索引,仅a生效)
- 不走索引(或仅用于排序):WHERE b = ?(跳过a,无法使用该索引);WHERE c = ?(完全跳过前缀)
单列索引 vs 多列索引:执行成本差异在哪?
成本模型主要体现在三方面:索引页读取量、回表次数、以及优化器对索引过滤率的预估精度。
- 索引体积与I/O开销:多列索引比单列索引更大,B+树层级可能更高,范围扫描时需读取更多页;但若能避免回表(覆盖索引),整体I/O反而更低
- 选择性叠加效应:(a,b) 的联合选择性通常高于单独 a 或 b;优化器基于统计信息估算匹配行数,联合条件用多列索引时预估更准,更倾向选它
- 回表代价:单列索引查出大量主键再回表,可能远慢于多列索引直接定位+覆盖输出(例如 SELECT a,b FROM t WHERE a=? AND b=?)
什么情况下该优先建多列索引?
满足以下任一条件,就值得考虑多列索引替代多个单列索引:
- 高频出现固定列组合的等值查询(如 user_id + status)
- 查询含 ORDER BY 或 GROUP BY,且字段顺序与索引前缀一致(如 ORDER BY a,b)
- SELECT 列全部被索引覆盖(避免回表),尤其在大表+高并发场景下收益明显
- 存在多个单列索引但优化器常只选其一,导致其他条件无法高效过滤(此时多列索引可一次性完成过滤)
一个典型误判:以为“建了(a,b)就不需要a了”
实际上,如果存在大量仅按 a 查询的语句,而 (a,b) 索引因 b 列数据分布不均(如大量NULL或重复值)导致 a 的等值查找效率下降,那么单独的 (a) 索引仍有必要。
- 可通过
EXPLAIN对比 key_len 和 rows 验证:同样 WHERE a = ?,单列索引 key_len 更小、rows 预估更少,说明更优 - MySQL 8.0+ 支持直方图统计,能改善多列索引下非前缀列的过滤率估算,但不能替代合理设计
真正影响成本的不是列数多少,而是索引结构与实际查询模式的匹配度。先观察慢日志中的高频 WHERE/ORDER BY 组合,再结合 EXPLAIN 的实际执行路径做决策,比套用“应该建复合索引”的经验更可靠。










