MySQL索引失效导致全表扫描、查询变慢、CPU升高、锁等待加剧;关键在于优化器仅在利用索引有序性或等值查找时使用索引,如违反最左前缀原则(如WHERE b=2 AND c=3)或对索引列用函数(如YEAR(create_time)=2024)均会失效。

MySQL索引失效会直接导致全表扫描,查询变慢、CPU升高、锁等待加剧。避免失效的关键是理解优化器如何使用索引——它只在能利用索引有序性或等值查找的场景下才走索引。
最左前缀原则被破坏
联合索引(a,b,c)本质上是先按a排序,a相同再按b排序,b也相同时再按c排序。一旦跳过左侧列,右侧列就无法使用索引。
- ✅ WHERE a = 1 AND b = 2:走索引
- ✅ WHERE a = 1 AND b = 2 AND c > 3:a、b用等值,c用范围,仍走索引(c部分用于过滤,但不参与排序)
- ❌ WHERE b = 2 AND c = 3:没用a,索引完全失效
- ❌ WHERE a > 1 AND c = 3:a是范围,b缺失,c无法利用索引
对索引列做计算或函数操作
优化器无法将表达式映射回原始索引值,只能放弃索引。
- ❌ WHERE YEAR(create_time) = 2024:函数作用于列 → 全表扫描
- ✅ 改为:WHERE create_time >= '2024-01-01' AND create_time 2025-01-01'
- ❌ WHERE UPPER(name) = 'ABC'
- ✅ 建函数索引(MySQL 8.0+):CREATE INDEX idx_name_upper ON t1 ((UPPER(name))),或统一存大写避免运行时转换
隐式类型转换
当查询条件与索引列类型不一致,MySQL自动转换时可能放弃索引。
- ❌ 字段是 VARCHAR(20),却写 WHERE col = 123(数字)→ 触发隐式转换,索引失效
- ✅ 统一类型:WHERE col = '123'
- ⚠️ 特别注意:数值型ID字段若定义为字符串(如订单号),务必用引号;反之整型主键不要加引号
使用不满足索引特性的操作符
不是所有WHERE条件都能用上索引,尤其涉及范围、NULL、NOT等逻辑时需谨慎。
- ❌ WHERE a != 1 或 WHERE a NOT IN (1,2):通常不走索引(除非覆盖索引+优化器认为划算)
- ❌ WHERE a IS NULL:如果a是普通索引且允许NULL,IS NULL 可走索引;但 IS NOT NULL 在非唯一索引上常失效
- ❌ WHERE a LIKE '%abc':前导通配符,无法利用B+树有序性
- ✅ 改为:WHERE a LIKE 'abc%'(后缀匹配可走索引)
- ✅ 模糊查全字段?考虑全文索引或ES










