联合索引必须遵循最左前缀原则:查询条件须从最左字段开始连续匹配;如索引(age,name,sex),仅age、(age,name)、(age,name,sex)有效,单独name或sex无法使用索引。

联合索引不是把几个字段堆在一起就行,关键在怎么用——核心就一条:必须从最左边的字段开始,连续、不跳过地匹配查询条件。
最左前缀原则到底是什么
比如你建了联合索引 (age, name, sex),MySQL 实际上自动为你准备了三组可用索引:
- (age) —— 单独查 age 能用上
- (age, name) —— 查 age 和 name 组合能用上
- (age, name, sex) —— 全三个字段都查也能用上
但注意:name = '张三' 或 sex = '女' 单独出现,这个索引完全不会被使用。因为 B+ 树是按 age 先整体排序的,没有 age 就找不到数据在哪一块,只能全表扫描。
哪些写法能走索引,哪些不能
继续以 (age, name, sex) 索引为例:
- ✅ WHERE age = 25 —— 走 (age)
- ✅ WHERE age = 25 AND name = '李四' —— 走 (age, name)
- ✅ WHERE age = 25 AND name = '李四' AND sex = '男' —— 走完整索引
- ❌ WHERE name = '李四' —— 缺少 age,索引失效
- ❌ WHERE name = '李四' AND sex = '男' —— 同样缺 age,跳过了最左列
- ⚠️ WHERE age > 30 AND name = '王五' —— age 是范围查询,name 还能用上;但 sex 就失效了(范围查询右侧列不参与索引)
实际建索引时的建议
别光看字段个数,要结合高频查询模式来排顺序:
- 把 过滤性最强 的字段放最左(比如 status = 'active' 比 city = '北京' 匹配行数少很多,就优先放前面)
- 把 经常一起出现在 WHERE 条件里 的字段尽量凑成一组,且保持顺序一致
- 如果查询常带 ORDER BY 或 GROUP BY,把排序/分组字段也考虑进索引顺序(例如 WHERE dept_id = ? ORDER BY create_time DESC,可建 (dept_id, create_time))
- 想避免回表?把 SELECT 中需要的字段也加进联合索引末尾,构成覆盖索引(如 SELECT id, name FROM user WHERE age = 25 AND name LIKE '张%',可建 (age, name, id))
容易被忽略的细节
即使写了所有字段,也可能意外失效:
- 对索引字段做函数或运算:WHERE YEAR(create_time) = 2025 → 不走索引;改成 create_time >= '2025-01-01' AND create_time 才行
- 字符串字段没加引号:WHERE name = zhang(缺少 '')→ 类型隐式转换,可能丢索引
- 用 OR 连接不同字段:WHERE age = 25 OR name = '张' → 整体索引失效(除非两个字段都有独立索引且满足某些条件)
- 模糊查询写成 LIKE '%张' → 前导通配符,索引无法定位起始位置










