复合索引遵循最左前缀原则,查询必须包含最左列才能有效利用B+树结构,否则触发全表扫描或文件排序;ORDER BY和SELECT覆盖也需匹配索引列序与方向。

因为复合索引底层是 B+ 树,数据按索引列从左到右排序存储,查询必须满足“最左前缀”才能跳过全表扫描。
复合索引的 B+ 树结构决定了顺序不可逆
MySQL 的 InnoDB 使用 B+ 树组织复合索引,比如 (user_id, create_time),树节点先按 user_id 排序,user_id 相同时再按 create_time 排序。这意味着:只有查询条件包含最左侧的 user_id,才能定位到某一段子树;跳过它直接查 create_time,引擎就只能遍历整棵树——等价于全表扫描。
常见错误现象:EXPLAIN 显示 type=ALL 或 Extra=Using filesort,尤其在 ORDER BY 多字段时更明显。
- 有效查询(命中索引):
WHERE user_id = 100 AND create_time > '2025-01-01' - 无效查询(索引失效):
WHERE create_time > '2025-01-01'或WHERE create_time > '2025-01-01' AND user_id = 100(条件顺序不影响,但缺失最左列就失效) -
ORDER BY必须与索引列顺序和方向一致,例如索引是(a, b DESC),则ORDER BY a, b DESC可避免Using filesort;换成ORDER BY a DESC, b就会失效
列顺序不只看 WHERE,还要看 ORDER BY 和 SELECT 字段
一个复合索引是否被完全利用,取决于整个查询执行路径:WHERE 过滤、ORDER BY 排序、SELECT 是否覆盖(即“覆盖索引”)。三者对列顺序的要求叠加后,才是最终设计依据。
使用场景举例:高频查询是 WHERE user_id = ? AND status = ? ORDER BY created_at DESC,且只查这三字段。
- 若建
(user_id, status, created_at):WHERE 部分能用上,但ORDER BY created_at是单字段,而索引中它排第三,无法跳过前两列做有序扫描 → 触发Using filesort - 若建
(user_id, status, created_at DESC):仍不行,因为created_at不是最左连续前缀,排序无法直接利用 - 正确做法是把排序字段提前,如
(user_id, created_at DESC, status)—— 前两个字段满足 WHERE + ORDER BY 联合需求,且status在最后不影响排序有效性
高选择性字段放前面 ≠ 总是正确
很多人误以为“区分度高的字段(如 email)一定要放最左”,但这只在它参与 WHERE 等值查询时才有意义。如果该字段很少单独出现在查询条件里,强行放最左反而浪费索引空间、降低其他更常用组合的命中率。
参数差异关键点:
-
WHERE user_id = ? AND email = ?:user_id通常比email更常作为外键或分页主键,即使 email 选择性更高,也应优先保证业务主路径的最左匹配 -
WHERE email = ?单独出现频率高 →email放最左合理;但若几乎不存在,就不该为它牺牲主要查询路径 - 索引宽度影响性能:VARCHAR(255) 放最左,比 INT 放最左占用更多内存和磁盘页,B+ 树层级可能变深
别依赖优化器自动“选最优”,必须用 EXPLAIN 验证
MySQL 优化器不会重排你写的 WHERE 条件顺序来适配索引,它只判断当前条件能否匹配最左前缀。哪怕你写了 WHERE create_time > ? AND user_id = ?,只要索引是 (user_id, create_time),它仍能用上;但若索引是 (create_time, user_id),这个查询就只能用 create_time 部分,user_id 变成回表过滤条件,性能断崖下跌。
实操建议:
- 对每个核心 SQL,运行
EXPLAIN FORMAT=TRADITIONAL,重点看key、key_len、rows、Extra -
key_len值能告诉你实际用了索引的几列(比如key_len=8对应前两列 INT,说明只用到最左两列) - 不要假设“建了索引就一定生效”,尤其是涉及
JOIN、GROUP BY、函数操作(如WHERE DATE(create_time) = ?)时,索引极易失效
真正容易被忽略的是:同一个索引,在不同查询中可能只发挥部分作用;而一个看似冗余的列顺序调整,可能让原本 rows=100000 的查询降到 rows=1。











