mysql索引什么时候会失效_mysql常见失效场景解析

来源:这里教程网 时间:2026-02-28 20:47:04 作者:

WHERE 里用了函数或表达式,索引直接不走

MySQL 的索引存的是字段原始值,一旦你在

WHERE
条件里对索引列做计算或调用函数,InnoDB 就没法拿索引树里的值去直接比对了。比如
WHERE YEAR(create_time) = 2023
,哪怕
create_time
有索引,也白搭。

❌ 错误写法:
WHERE DATE(order_date) = '2024-04-21'
WHERE price * 1.1 > 100
WHERE LEFT(name, 3) = 'Joh'
✅ 正确改法:把函数“挪”到右边,转成范围查询——
WHERE order_date >= '2024-04-21' AND order_date 、<code>WHERE price > 100 / 1.1
⚠️ 注意:
CAST()
或隐式转换(比如字符串字段查数字)本质也是函数,同样失效,别以为只是“少个引号”而已

联合索引没按最左前缀用,后边全作废

复合索引

(a, b, c)
是按 B+ 树的层级顺序组织的:先排 a,a 相同再排 b,b 相同再排 c。跳过前面的列,就等于找不到入口,整棵树都用不上。

❌ 失效场景:
WHERE b = 2 AND c = 3
(没 a)、
WHERE a = 1 AND c = 3
(跳过 b)、
WHERE a > 10 AND b = 5
(a 是范围,b 后续失效)
✅ 解法不是硬凑条件,而是看高频查询反推索引设计:如果常查
city
district
,就建
(city, district)
,别为了“覆盖更多”硬塞个
(country, city, district)
却总只查后两列
? 补充:范围查询(
BETWEEN
>
LIKE 'abc%'
)会让其后的索引列失效,不是“不能建”,是“建了也用不上”

LIKE 左模糊、OR 混合无索引列、IS NOT NULL 都容易踩坑

这些看着像语法糖的操作,底层其实破坏了索引的有序性或可预估性,优化器一算——不如全表扫快。

WHERE name LIKE '%john'
:B+ 树没法从中间开始找,必须逐行扫
WHERE a = 1 OR b = 2
:如果只有
a
有索引、
b
没索引,MySQL 往往放弃索引合并,直接全表扫描
WHERE status IS NOT NULL
:B+ 树默认不存
NULL
值,查非空就得挨个判断,除非你显式为该列建索引(且字段本身允许
NULL
✅ 应对:左模糊换全文索引或应用层反向索引;
OR
拆成
UNION ALL
或给所有涉及列补索引;
IS NOT NULL
查询频繁就加
NOT NULL
约束,或单独建索引

类型不一致、数据太偏斜,优化器主动弃疗

有时候索引明明存在、写法也没错,但执行计划里

type
还是
ALL
——不是 bug,是优化器在“理性放弃”。

❌ 字段是
VARCHAR
,却写
WHERE phone = 13800138000
:MySQL 自动加
CAST(phone AS UNSIGNED)
,索引失效
❌ 某个值占全表 95%,比如
status = 'active'
,优化器发现走索引还要回表 95% 的记录,不如直接扫聚簇索引
✅ 验证手段只有一个:
EXPLAIN
key
是否命中、
rows
是否合理、
Extra
有没有
Using filesort
Using temporary
⚠️ 最容易被忽略的一点:统计信息过期。大批量导入后没跑
ANALYZE TABLE
,优化器还按旧分布估算,可能误判索引价值

相关推荐