深蓝黑背景品牌封面:左侧大标题「建了索引,还是全表扫描」,副标题「索引失效的典型写法,与执行计划验证法」;右侧原创装饰——一张数据表网格上放着一个放大镜,镜下索引列被画上一个红色叉号;顶部标注「经典面试题解析 · 数据库」与「Day 03 · 09-21」 图 1:本文封面,点明题目「索引失效」与排查手段。

先说明属性:这是一篇经典题解析,题目出自本地历史面试资料(见文末来源说明),与任何公司的当前招聘无关。这是一道「背得出清单、讲不清原理」的重灾区题目——面试官想听的不是五种失效写法的罗列,而是它们背后同一条原因,以及你怎么证明索引真的没被用上。

想象面试现场:一张百万行的订单表,create_time 上建了索引,但 WHERE DATE(create_time) = '2026-09-01' 慢得要命。面试官问:为什么?

第一步,审题。

先建立一个总原则:MySQL 官方文档说得很清楚,索引的价值是「不用读整张表就能定位到行」。一旦你的写法让优化器无法利用索引树里的有序结构做查找,它就只能退回全表扫描——扫一百万行和查几百行,差的不是常数是数量级。

第二步,基础回答:五种典型失效写法与共同根因。

一,对索引列套函数或表达式。WHERE DATE(create_time) = ... 里索引树按原始值排序,函数算出来的值树里没有,只能逐行计算再比较。正确写法是把计算挪到常量一侧:WHERE create_time >= '2026-09-01' AND create_time < '2026-09-02'。

二,LIKE 以百分号开头。LIKE '%abc' 要求匹配任意后缀,而索引树是按前缀有序的,前缀匹配 LIKE 'abc%' 才能走索引。

三,隐式类型转换。字符串列拿数字去比(WHERE phone = 138...),官方文档明确说明:不同类型之间的比较需要转换时可能阻止索引使用——因为转换发生在列的一侧,等价于对整列套了函数。

四,OR 两侧不都有索引。WHERE a = 1 OR b = 2,只要一侧没索引,优化器就得为那一侧全表扫描,干脆整体全扫。

五,联合索引不满足最左前缀。官方文档写明:多列索引上,优化器能用的是索引的最左前缀。索引是 (a, b, c),条件只有 b 和 c 没有 a,等于从中间查字典,索引用不上。

五种写法背后是同一个根因:你的条件没有落在索引树的有序结构上。记住这一句,清单不用背。

第三步,怎么证明:EXPLAIN 执行计划。

猜索引失不失效没有意义,用 EXPLAIN 看执行计划。官方文档说明 EXPLAIN 输出优化器将如何执行语句,重点看三列:type 是访问类型,ALL 就是全表扫描,走到 ref、range 才算用上索引;key 显示实际使用的索引名,NULL 就是没用;rows 是预估扫描行数,走索引时几十几百行,失效时接近全表行数。MySQL 8.4 还支持 EXPLAIN ANALYZE,真正执行一遍并给出实际耗时与行数,估算和现实对不上时用它。如果索引存在却死活不用,文档建议跑 ANALYZE TABLE 更新表统计信息,优化器的判断是基于统计的。

对照图:左侧列出索引失效的五种典型写法——对索引列套函数(如 DATE(create_time))、LIKE 以百分号开头、字符串列用数字比较触发隐式类型转换、OR 两侧不都有索引、联合索引不满足最左前缀;右侧给出 EXPLAIN 执行计划对照——走索引时 type 为 ref、key 显示索引名、扫描行数约百行,失效时 type 为 ALL、key 为 NULL、扫描近百万行。底部排查套路:慢查询先 EXPLAIN,看 type、key、rows 三列,再对照失效清单改写法;执行计划细节以当前 MySQL 官方文档为准 图 2:五种失效写法与 EXPLAIN 三列对照排查法。

第四步,可能的追问。

「没犯这五种错,索引还是没走?」优化器是基于代价决策的:官方文档提醒,当查询需要访问表里大部分行时,顺序读比走索引更快,优化器会主动放弃索引——小表、高过滤比低的情形都可能触发。「怎么根治?」慢查询日志捞出慢 SQL,先 EXPLAIN 看三列,再对照失效清单改写法;改不了写法就改索引(联合索引顺序、覆盖索引)。覆盖索引值得一提:查询要的列都在索引里时,连回表都省了,这是正向优化而不是避坑。

易错点清单。

一,把「建了索引」当成「索引生效」,从不看执行计划。二,只记得背五种写法,讲不出「条件没落上有序结构」这个总原则。三,以为优化器不用索引一定是 bug——它有时代价估算就是对的。四,改了 SQL 不重新 EXPLAIN 验证,凭感觉上线。

回到面试现场,建议的答题节奏:先立总原则,再给两三个最典型例子(函数、前导百分号、最左前缀),然后主动演示 EXPLAIN 三列怎么读,最后补一句「优化器基于代价,不用索引有时是合理决策」。有原则、有例子、有验证手段,这题就答圆了。

AI 应用的元数据查询、样本检索都跑在 SQL 上,慢查询拖垮数据管道时,索引排查是第一优先级。你排查过最隐蔽的一次索引失效是什么原因?欢迎分享。

参考资料

  • How MySQL Uses Indexes(MySQL 8.4 官方文档:索引避免全表扫描、联合索引最左前缀、类型转换可能阻止索引使用、需访问大部分行时优化器倾向顺序读、覆盖索引) — https://dev.mysql.com/doc/refman/8.4/en/mysql-indexes.html
  • EXPLAIN Statement(MySQL 8.4 官方文档:EXPLAIN 输出执行计划、type/key/rows 等列含义、EXPLAIN ANALYZE 实际执行、ANALYZE TABLE 更新统计信息) — https://dev.mysql.com/doc/refman/8.4/en/explain.html