MySQL 中使用索引一定有效吗?如何排查索引效果?
- 标签:后端、MySQL、数据库、场景题
🏛 业务架构师
索引不是免死金牌,建了索引不一定被使用,使用了也不一定更快。常见的失效与低效场景:
- 对索引列做函数或运算(
date(created_at)=?、id+1=?); - 隐式类型转换:字符串列用数字查(
phone=13800000000),索引直接失效,这是线上高频事故; - 前导模糊查询
like '%xx'; - 低选择性:性别、状态这类只有几个取值的列,单独建索引意义有限,优化器可能估算全表扫描更便宜;
- 优化器成本估算偏差:统计信息过旧导致选错索引。
排查方法我是标准动作三步:
EXPLAIN看 type(至少 range,出现 all 就要警惕)、key 是否命中预期索引、rows 预估行数、Extra 是否 filesort/temporary;SHOW INDEX FROM 表看索引基数(Cardinality),过低说明选择性差;- 开启 optimizer trace 分析优化器为什么放弃索引,必要时 analyze table 更新统计信息。
架构师视角的结论:索引是运营出来的资产,不是一次性设计。要有慢查询采集、EXPLAIN 卡点、定期索引有效性评审的机制——查询模式随业务迭代漂移,索引也要跟着生命周期管理,否则半年后就成一堆没人敢删的死索引。
🏗 系统架构师
不一定有效,这是我在性能治理中反复验证过的结论。索引可能失效或不被选择的常见情形:
- 写法层面:对索引列做函数/运算(
date(create_time)=...、id+1=10)、隐式类型转换(varchar 列用数字查)、前导模糊 like、or 连接非索引列; - 统计信息层面:优化器基于成本估算,回表代价高、区分度低(性别列)或统计信息过期时,可能直接选全表扫描——这时"用了索引反而更慢";
- 数据量层面:结果集占比超过 20~30% 时全表顺序扫优于随机回表。
排查方法:先 EXPLAIN 看 key、rows、Extra;对比 force index 与默认计划的实际耗时;show index from t 看 Cardinality 区分度;必要时 analyze table 校正统计信息;配合慢日志 + pt-query-digest 找到真正该优化的 SQL。
我的原则:索引效果要用线上真实数据分布验证,不能凭建索引时的想象,上线前在从库跑 explain 是硬性流程。
💻 全栈开发专家
不一定。索引建了不代表会走,常见失效场景我按踩坑频率排:
- 隐式类型转换:
WHERE phone = 13800000000(phone 是 varchar),相当于对列套函数,索引失效。字符串列条件必须带引号。 - 对索引列做函数或运算:
DATE(create_time) = '2026-10-24'失效,改成范围create_time >= '2026-10-24' AND < '2026-10-25'。 - 前导模糊:
LIKE '%xx'失效('xx%'可以走 range)。 - 优化器算出来走索引成本更高:区分度低(比如性别列),或大范围查询回表太多,宁可全表扫。
排查三步法(我处理慢 SQL 的固定动作):
sql
EXPLAIN SELECT ...; -- 看 type、key、rows、Extra
-- key 是 NULL 或 type=ALL 就是没走索引- 打开 optimizer_trace 看优化器为什么放弃(cost 对比);3. 确认统计信息是否过期,必要时
ANALYZE TABLE重算。改完后用EXPLAIN FORMAT=TREE对比实际执行计划和耗时,别只凭 key 列判断就收工。