mysql索引为什么会失效_mysql索引失效原因解析

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

MySQL索引失效,本质是优化器判断走索引的代价高于全表扫描,于是主动放弃使用索引。它不是“坏了”,而是“不划算”或“用不了”。真正影响执行计划的关键,在于查询写法是否匹配索引结构、数据是否可被高效定位。

联合索引没按最左前缀匹配

比如建立了 (sn, name, age) 联合索引,只有以下条件能用上索引:

sn = ? sn = ? AND name = ? sn = ? AND name = ? AND age = ?

name = ?name = ? AND age = ? 就完全跳过索引——因为B+树是按 sn 排序的,没有 sn 就不知道从哪开始找。中间断开(如只用 sn 和 age,跳过 name)也会导致后续列失效。

查询条件破坏了索引值的有序性

索引依赖字段原始值的有序存储,一旦被干扰,就无法做范围查找或等值跳转:

对字段用函数:如
WHERE UPPER(name) = 'LISA'
WHERE DATE(create_time) = '2025-12-01'
对字段做运算:如
WHERE price * 1.1 > 100
WHERE id + 1 = 1000
隐式类型转换:字段是
VARCHAR
,却写成
WHERE mobile = 13812345678
(MySQL会转成字符串比较,但过程不可下推到索引层)

模糊查询位置不当

只有前缀匹配能用索引:

LIKE '张%'
✅ 可走索引(知道起始位置)
LIKE '%张'
❌ 全表扫描(结尾不确定,无法定位起点)
LIKE '%张%'
❌ 同样无法定位,除非是全文索引

注意:

LIKE '张_'
(单字符通配)或
LIKE '张__'
仍可走索引,因为前缀固定且长度可控。

其他常见触发点

这些情况容易被忽略,但同样让索引“形同虚设”:

OR 条件中混用无索引列:如
WHERE indexed_col = 1 OR unindexed_col = 'x'
→ 整个条件放弃索引
IS NOT NULL 对非空字段无效:如果字段定义为
NOT NULL
,再写
WHERE col IS NOT NULL
,优化器认为恒真,可能跳过索引
数据量太小或选择率太高:比如表仅千行,或
WHERE status = 1
匹配了95%的数据,优化器倾向直接扫表
统计信息过期:执行过大量 INSERT/DELETE 未 ANALYZE TABLE,优化器基于错误基数估算,误判索引价值

相关推荐