MySQL索引失效本质是优化器认为走索引代价高于全表扫描,关键在于查询是否匹配索引结构及数据能否高效定位:1.联合索引须遵循最左前缀;2.避免函数、运算、隐式转换破坏有序性;3.LIKE仅前缀匹配有效;4.OR含无索引列、IS NOT NULL冗余、数据量小或统计过期等均致失效。

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,优化器基于错误基数估算,误判索引价值










