欢迎光临
我们一直在努力

MySQL 索引失效的 12 种情况,每条都能用 explain 验证

先给结论

12 种:索引列上套函数、索引列参与运算、隐式类型转换、字符集或排序规则不一致、前导通配符、违反最左前缀、范围条件之后的列、OR 连了非索引列、不等类条件、区分度过低、统计信息过期、排序分组与索引不匹配。

它们分成两大类:前八种是写法让索引\”用不上\”,后四种是优化器算完成本主动放弃。这个分法比背清单有用。

一个典型的排查现场

很多团队上线前都会遇到这类事:一张订单表,status 和 create_time 都建了索引,某个查询却慢得离谱,慢日志里平均 3.6 秒。

翻代码,SQL 长这样:

SELECT order_no, amount FROM t_order
WHERE DATE(create_time) = \’2026-10-01\’
AND status = 2;

create_time 上明明有索引。加 EXPLAIN 一看,type 是 ALL,key 是 NULL,rows 估算四百多万,确实没走。

改成范围写法:

SELECT order_no, amount FROM t_order
WHERE create_time >= \’2026-10-01 00:00:00\’
AND create_time < \’2026-10-02 00:00:00\’
AND status = 2;

再 EXPLAIN,type 变成 range,rows 掉到几千,实测从 3.6 秒降到 0.02 秒量级。数字以你自己的环境为准,量级差是真实的。

差别只有一处:DATE() 这个函数被去掉了。

先搞清楚\”失效\”到底是什么

这是全篇最重要的一句:索引失效不是索引坏了,是优化器算了成本之后决定不用它。

MySQL 优化器基于成本估算选路径。走二级索引要回表,回表是随机 IO;全表扫描是顺序 IO,读得多但一次能读一整个区。估算命中行数超过全表某个比例时,它会认为顺序扫更快,于是放弃索引。

这个比例不是固定值,常见说法在 20% 到 30% 区间,还受统计信息和页聚簇程度影响,别当硬阈值背下来。

排查顺序:先看 EXPLAIN,确认优化器选了什么;再判断是\”用不上\”还是\”不想用\”。前者改 SQL,后者改数据分布或用 FORCE INDEX 兜底。

EXPLAIN 四个字段够用了:

  • type:从坏到好是 ALL、index、range、ref
赞(0)
未经允许不得转载:171主机测评 » MySQL 索引失效的 12 种情况,每条都能用 explain 验证
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址