
联合索引失效的常见原因
联合索引(如 INDEX (a, b, c))不是简单把多个字段拼在一起,而是按定义顺序构建 B+ 树:先按 a 排序,a 相同时再按 b 排序,b 也相同时再按 c 排序。只要查询条件没用上最左字段,或者中间断开,就无法利用索引的有序结构,导致失效。
最左前缀原则被破坏
这是联合索引失效最典型的情况。MySQL 只能使用索引的连续前缀部分,一旦跳过某个字段,后续字段即使出现在 WHERE 中也无法走索引。
- 有效使用:WHERE a = 1;WHERE a = 1 AND b = 2;WHERE a = 1 AND b = 2 AND c = 3
- 部分失效:WHERE b = 2 —— a 没出现,整个索引无法定位,全表扫描
- 中间断开:WHERE a = 1 AND c = 3 —— b 缺失,c 无法利用索引排序,只能用到 a
范围查询后的字段无法走索引
在联合索引中,遇到 >、
- INDEX (a, b, c),WHERE a = 1 AND b > 10 AND c = 5 → 实际只用到 a 和 b,c 不走索引
- WHERE a > 5 AND b = 2 → 只能用到 a,b 和 c 完全失效
- 注意:=、IN、IS NULL 是等值条件,不会截断;而 >=、
其他容易忽略的失效场景
除了最左匹配和范围中断,这些细节也常被面试官追问:
- 隐式类型转换:字段是 VARCHAR,却传入数字(如 WHERE a = 123),触发函数隐式转换,索引失效
- 对索引字段使用函数或运算:WHERE UPPER(b) = 'ABC' 或 WHERE a + 1 = 10,无法直接匹配索引值
- OR 条件混用非索引列:WHERE a = 1 OR d = 2(d 无索引),可能导致整个条件放弃使用索引
- SELECT * 导致回表代价高,优化器选择全表扫描:尤其当覆盖索引不成立、且查询行数占比大时
如何验证是否走联合索引
别靠猜,用 EXPLAIN 看执行计划:
- 关注 key 列:显示实际使用的索引名
- 看 key_len:计算值能反推出用了几个字段(如 INT 是 4 字节,VARCHAR(50) utf8mb4 算 200 字节),帮助判断是否“用全”了联合索引
- 留意 type:const / ref 表示高效索引访问;range 是范围扫描;ALL 是全表扫描
- Extra 中出现 Using index 说明是覆盖索引;出现 Using where; Using index 更理想;有 Using filesort 或 Using temporary 往往意味着排序/分组没走索引









