极高 进阶
索引失效场景#
一句话答案#
索引失效常见场景:LIKE 左模糊、对列函数计算、隐式类型转换、违反最左前缀、OR 含非索引列、否定条件。
核心要点
口诀:模头空函否全或
- LIKE以%开头
- 对索引列使用函数/计算
- 隐式类型转换(varchar和int比较)
- 联合索引未遵循最左前缀
- OR条件中有非索引列
- NOT IN / NOT EXISTS / !=
- 范围查询后的列
面试回答(2分钟版)
索引失效在实际开发中非常常见,我总结为七类。第一是对索引列使用函数或计算,比如 WHERE YEAR(create_time) = 2025,B+ 树无法直接定位,应改写为范围查询。第二是隐式类型转换,varchar 字段用数字匹配时 MySQL 会逐行转换导致索引失效。第三是 LIKE 左模糊如 LIKE ‘%abc’,B+ 树从左到右有序,左边不确定就没法走索引。第四是违反最左前缀原则,联合索引 (a,b,c) 查询只有 b 和 c 跳过了 a 就无法命中。第五是 OR 条件中有一边没索引就可能全表扫描,除非两边都有索引触发 index merge。第六是否定条件如 NOT IN、!= 通常无法利用索引定位。第七是范围查询右边列失效,WHERE a=1 AND b>2 AND c=3 中 c 用不到索引,因为 b 范围查询后 c 不再有序。本质上这些场景都是让 B+ 树无法按顺序定位,只能退化为逐行扫描。排查时通过 EXPLAIN 看 key 和 type 字段确认索引是否生效。
追问与易错
追问方向:
- “怎么验证索引是否生效?”→ 用 EXPLAIN 查看执行计划,key 列显示实际使用的索引(NULL 表示未走索引),type 列显示访问类型(ALL 为全表扫描需优化,ref/range 说明走了索引)
- “联合索引 (a,b,c) WHERE a=1 AND c=3 能用索引吗?”→ 只能用到 a 部分,因为跳过了 b 导致 c 在索引中不连续有序;但 MySQL 5.6+ 的 ICP 优化可在索引层额外过滤 c=3,减少回表次数
- “字符串不加引号为什么索引失效?”→ varchar 字段与数字比较时触发隐式类型转换,MySQL 将字段逐行转为数字再比较,无法利用索引的有序性,退化为全表扫描
易错点:
- ❌ “有索引就一定走索引”——优化器可能判断全表扫描更快(数据量小/返回行数多)
- ❌ “OR 一定不走索引”——两边都有索引时可以用 index merge