60 秒回答模板

可以按几类回答。第一,破坏索引有序性,例如对索引列使用函数、表达式计算、隐式类型转换,导致无法直接按 B+ 树顺序定位。第二,不符合联合索引最左前缀,例如跳过前导列,或者范围条件后面的列无法继续充分用于定位。第三,匹配方式不友好,例如 like 以通配符开头、or 条件两边索引不完整、not equal 选择性差。第四,优化器认为使用索引不划算,例如返回大量数据、统计信息偏差、回表成本过高。排查时应结合 explain 看 type、key、rows、filtered 和 Extra,而不是只凭 SQL 中是否写了索引列。

考点 有序性原则
难度 真实面经高频题
回答目标 讲清机制、边界和追问

深入解析

01

函数和表达式

如果在索引列上套函数或做表达式计算,例如对时间列取日期、对数字列加减、对字符串列截取,数据库往往无法直接利用原索引的有序结构。因为 B+ 树中保存的是原始列值的排序,不是计算后的结果。更好的做法是改写条件,让索引列保持单独比较,或使用生成列、函数索引等能力。

02

隐式类型转换

字段类型和查询常量类型不一致时,MySQL 可能发生隐式转换。如果转换作用在索引列上,就可能破坏索引使用。例如字符串列拿数字去比较,数据库可能把列值转换成数字再判断,原来的字符串索引顺序无法直接用于定位。写查询时要让参数类型和字段类型一致,尤其注意字符集、排序规则和数字字符串。

03

联合索引顺序

联合索引按照定义顺序组织键值,例如 a、b、c 的联合索引会先按 a 排,再按 b 排,最后按 c 排。如果查询跳过 a 直接查 b,通常无法有效利用这个联合索引。遇到范围条件时,范围列后面的列也常常不能继续用于精确定位,只可能在索引条件下推或过滤阶段发挥部分作用。

04

模糊和否定条件

like 如果以通配符开头,前缀不确定,B+ 树无法定位起始范围,因此普通索引通常难以高效使用。not equal、not in、is not null 这类否定条件也可能选择性较差,优化器可能认为走索引后仍要扫描大量记录并回表,不如直接扫描表。它们不是绝对不能用索引,而是经常不够划算。

05

优化器成本选择

很多所谓索引失效,本质是优化器估算后选择了全表扫描。比如表很小、条件命中比例很高、需要回表的数据很多、统计信息不准确、order by 与 where 无法同时利用同一索引,都可能让索引路径成本更高。排查时要看执行计划和实际扫描行数,必要时更新统计信息或调整索引设计。

易错点

  • 把索引失效说成固定规则,忽略优化器会根据数据分布和成本动态选择。
  • 只背最左前缀原则,却说不清联合索引的排序方式和范围条件影响。
  • 认为 like、or、not in 一定完全不能走索引,没有区分具体写法和选择性。
  • 排查时只看 SQL 文本,不看 explain、实际扫描行数和回表成本。

面试官追问

like 一定会导致索引失效吗?

不一定。like 'abc%' 有明确前缀,通常可以利用普通 B+ 树索引做范围查询;like '%abc' 或 like '%abc%' 前缀不确定,普通索引通常难以有效利用。

联合索引中范围条件后的列完全没用吗?

不一定。范围条件后的列通常不能继续用于精确缩小索引扫描范围,但可能通过索引条件下推在存储引擎层过滤,或者用于覆盖索引减少回表。要结合执行计划判断。

or 条件为什么容易不走索引?

如果 or 两边不是都能有效利用索引,或者合并多个索引的成本高,优化器可能选择全表扫描。可以考虑拆成 union all、补齐合适索引,或者重写条件。

explain 里 key 有值就说明索引完全生效了吗?

不是。key 只表示执行计划选择了某个索引,还要看 type、rows、filtered、Extra,以及是否出现 Using index、Using index condition、Using filesort、Using temporary。索引可能只被部分利用。