联合索引生效需遵循最左前缀原则,即查询条件必须从索引最左列开始连续匹配,范围查询后右侧列失效,排序分组也须符合该顺序;设计时应按等值→范围→排序列顺序创建,并用EXPLAIN验证。

联合索引(也叫复合索引)在 MySQL 中是提升多条件查询性能的关键手段,但它的生效有明确规则,并不是只要建了就一定起作用。核心在于最左前缀原则——查询条件必须从索引的最左边列开始连续匹配,中间不能跳过。
联合索引的结构和最左前缀原则
比如你创建了联合索引 INDEX idx_name_age_dept (name, age, dept),它实际构建的是按 name 排序 → 在 name 相同下按 age 排序 → 在 name 和 age 都相同时按 dept 排序的 B+ 树。因此只有满足“从左到右连续”的查询条件才能走索引:
-
WHERE name = '张三'✅ 走索引(只用第一列) -
WHERE name = '张三' AND age > 25✅ 走索引(用了前两列,age 可用于范围查找) -
WHERE name = '张三' AND age = 25 AND dept = '技术部'✅ 全部命中 -
WHERE age = 25❌ 不走索引(跳过了 name) -
WHERE name = '张三' AND dept = '技术部'⚠️ 只能用上 name,dept 因为中间断开(缺少 age)无法利用索引排序,会回表或全扫 dept 部分
范围查询之后的列无法使用索引
一旦某列用了范围(>、、BETWEEN、LIKE 前缀不固定如 '%abc'),其右侧所有列都失效:
-
WHERE name = '张三' AND age > 25 AND dept = '技术部'→ dept 列不生效 -
WHERE name LIKE '张%'→ 是范围,但属于最左列的“有效范围”,后续列仍可继续判断(因为 B+ 树中 '张%' 是连续区间) -
WHERE name LIKE '%张'→ 不符合最左前缀,整个索引失效
排序和分组也遵循最左前缀
如果 SQL 中有 ORDER BY 或 GROUP BY,想避免 filesort,字段顺序必须和联合索引最左连续部分一致,且方向(ASC/DESC)要匹配(MySQL 8.0+ 支持混合方向,但老版本要求全部一致):
-
ORDER BY name, age✅ 可利用(name, age, dept) -
ORDER BY age, dept❌ 无法利用(没包含 name) -
ORDER BY name DESC, age ASC❌ MySQL 5.7 默认不支持混合排序,会触发 filesort
如何设计高效的联合索引
建索引前先看高频查询模式,优先把等值查询列放前面,再放范围列,最后放排序/分组列。例如常见查询是:WHERE status = ? AND create_time > ? ORDER BY update_time DESC,那就建 INDEX idx_status_time_update (status, create_time, update_time)。
- 区分度高的列不必强求放最前,等值条件的列顺序优先级更高
- 避免冗余索引:已有
(a,b,c)就不用单独建(a)或(a,b) - 用
EXPLAIN验证:重点看key(是否命中)、key_len(用了索引多少字节,可反推用了几列)、Extra(有没有 Using where / Using index / Using filesort)









