MySQL索引失效10个场景

引言

很多慢查询并不是“没建索引”,而是“建了没用上”。排查时别先加新索引,先确认现有索引为何失效。

场景1:在索引列上做函数运算

示例:where date(create_time) = '2026-03-05'

函数会破坏有序性,导致无法走范围扫描。改为:

where create_time >= '2026-03-05 00:00:00' and create_time < '2026-03-06 00:00:00'

场景2:隐式类型转换

user_id 是字符串,却用数字比较,MySQL 可能做全表转换。类型统一是前提。

场景3:最左前缀未命中

联合索引 (a,b,c),只查 b,c 往往用不上。条件顺序应从左到右利用索引前缀。

场景4:like '%xxx'

前置通配符会导致无法利用 B+Tree 前缀匹配。可以考虑:

  • 改业务搜索规则
  • 引入倒排索引(ES)

场景5:or 条件一侧无索引

where a = ? or b = ?,若 b 无索引,优化器常放弃索引方案。

场景6:选择性太差

例如性别、状态位这类低基数字段,单列索引收益有限。可结合高选择性字段做联合索引。

场景7:排序与索引方向不匹配

where a = ? order by b,若索引不是 (a,b),容易出现 filesort

场景8:回表成本高,优化器放弃

即便可以走索引,但回表太多,优化器可能选全表扫描。可用覆盖索引减少回表。

场景9:统计信息过期

表数据分布变化后,执行计划可能退化。需要定期 ANALYZE TABLE

场景10:SQL写法导致范围过宽

范围条件放在联合索引中间列,会截断后续列利用。索引设计要匹配高频查询形态。

快速排查流程

  1. EXPLAINtype/key/rows/extra
  2. 开启 EXPLAIN ANALYZE 看真实执行耗时。
  3. 检查是否出现 Using filesortUsing temporary
  4. 对照慢日志确认是否为高频 SQL。

索引治理建议

  • 每张核心表维护“主查询清单”。
  • 索引命名体现用途,如 idx_order_user_status
  • 定期清理长期未命中的冗余索引。
  • 新增索引必须附带可回滚方案。

总结

索引优化是“查询模式优化”,不是“字段越多索引越好”。先找失效原因,再改 SQL 与索引结构,才能稳定提效。

results matching ""

    No results matching ""

    results matching ""

      No results matching ""