联合索引仅在最左连续匹配时高效生效;跳过左侧列、中间缺列或范围查询后接等值条件均使右侧列失效;WHERE顺序不影响索引使用,但必须包含最左列;LIKE左前缀匹配有效,否则失效;ORDER BY须严格按索引列顺序避免filesort;覆盖索引可免回表但需权衡冗余成本。

联合索引不是“多个列堆在一起就能用”,它只在查询条件严格满足最左连续匹配时才高效生效。跳过左侧列、中间缺列、范围查询后接等值条件,都会让右侧列失效。
WHERE 条件顺序不影响索引匹配,但列是否出现才关键
MySQL优化器会自动重排 WHERE 子句中的条件顺序,所以 WHERE b = 2 AND a = 1 和 WHERE a = 1 AND b = 2 对联合索引 idx_a_b_c(a, b, c) 的使用效果一致。
- 真正决定能否走索引的是:是否包含最左列
a - 如果
a没出现在WHERE中(比如只写b = 2或c = 3),整个联合索引直接被跳过 - 执行计划里
key字段为空、type是ALL或index,基本可判定没走有效索引
范围查询(>、
联合索引 idx_status_ct_uid(status, create_time, user_id) 中,create_time > '2024-01-01' 是范围条件,它右边的 user_id 就无法用于快速定位,只能靠 Index Condition Pushdown(ICP)在引擎层过滤。
-
WHERE status = 1 AND create_time > '2024-01-01' AND user_id = 123→ 只用到前两列,user_id不加速查找 -
WHERE status = 1 AND create_time = '2024-01-01' AND user_id = 123→ 三列全用,B+ 树能精确定位叶子节点 -
LIKE 'abc%'算等值前缀匹配,不截断;但LIKE '%abc'或LIKE '%abc%'会导致该列完全失效
ORDER BY 必须严格按索引列顺序才能避免 filesort
联合索引的排序能力只对“从左开始连续”的列有效。即使 WHERE 匹配了全部三列,如果 ORDER BY 顺序和索引定义不一致,仍会触发 filesort。
-
ORDER BY status, create_time→ ✅ 利用索引有序性,无filesort -
ORDER BY create_time, status→ ❌ B+ 树中create_time并非全局有序,必须额外排序 -
ORDER BY status DESC, create_time ASC→ ⚠️ 混合方向时,MySQL 8.0+ 才支持,老版本会退化为filesort
覆盖索引能避免回表,但要小心字段冗余和维护成本
当 SELECT 的所有字段都包含在联合索引中(如 SELECT status, create_time FROM t WHERE status = 1 配合 idx_status_ct(status, create_time)),就构成覆盖索引,无需回主键索引查整行。
- 覆盖索引极大减少 I/O,尤其对宽表或高并发查询很有效
- 但每多加一列进索引,就会增大索引体积、拖慢 INSERT/UPDATE 速度
- 别盲目把常用查询字段全塞进一个联合索引——优先保障高频、高选择性的最左列,再根据实际
SELECT字段补足
最左前缀原则的本质是 B+ 树的排序结构限制,不是 MySQL 的“规则漏洞”或“优化技巧”。设计索引前,必须先看清楚业务中最常出现的 WHERE 组合、ORDER BY 顺序、以及 SELECT 字段——脱离这三点谈“最左前缀”,容易建出一堆好看但没用的索引。


















