SQL 查询超过 5 秒时,应立即使用 EXPLAIN 命令查看执行计划,重点检查 type 是否为 ALL 或 key 是否为 NULL。适用场景为 MySQL 数据库,风险边界是避免在生产主库直接执行复杂查询的 EXPLAIN 以免锁表。
先说结论:EXPLAIN 是定位慢查询索引失效的核心工具,通过分析执行计划中的 type 和 key 字段可确认是否走索引。
- 先定位:捕获慢查询日志或使用 SHOW PROCESSLIST 找到耗时 SQL。
- 先做:对目标 SQL 前缀添加 EXPLAIN 关键字执行分析。
- 再验证:优化索引后重新执行 EXPLAIN 确认 type 变为 ref 或 range 级别。
命令速用版
在原始查询语句前加上 EXPLAIN 关键字即可获取执行计划,MySQL 5.6.3 及以上版本建议使用 EXPLAIN FORMAT=JSON 获取更详细信息。
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
EXPLAIN FORMAT=JSON SELECT * FROM users WHERE email = 'test@example.com';
为什么会这样
索引失效通常是因为查询条件破坏了索引列的有序性或导致类型转换。常见原因包括对索引列进行函数运算、隐式类型转换或使用左侧模糊匹配。
MySQL 优化器在遇到无法利用索引树结构的情况时,会退化为全表扫描,导致查询时间随数据量线性增长。
分步处理
第一步:确认慢查询语句。通过慢查询日志或监控工具获取执行时间超过阈值的 SQL 文本。
第二步:执行 EXPLAIN 分析。在测试环境或从库上执行 EXPLAIN 加原始 SQL,避免锁表风险。
第三步:检查关键列。关注 type 列是否为 ALL,key 列是否为 NULL,Extra 列是否出现 Using filesort 或 Using temporary。
第四步:调整索引或写法。根据失效原因添加覆盖索引或修改 SQL 写法,避免在索引列上使用函数。
怎么验证是否生效
重新执行优化后的 EXPLAIN 命令,确认 type 列从 ALL 变为 ref、range 或 const,且 rows 扫描行数显著减少。
在实际业务低峰期执行优化后的 SQL,对比执行时间是否降至预期范围内。
常见坑
注意隐式类型转换,例如字符串类型的索引列使用数字查询会导致索引失效。
避免使用 OR 连接非索引列条件,这可能导致整个查询不走索引。
LIKE 查询以百分号开头时无法利用普通索引,需考虑全文索引或搜索引擎方案。
常见问题
问题
EXPLAIN 结果中 type 列哪些值表示性能较好?
答案
const、eq_ref、ref 和 range 表示使用了索引,性能通常优于 ALL 和 index 全扫描。
问题
为什么加了索引还是走全表扫描?
答案
可能因为数据分布导致优化器认为全表扫描成本更低,或查询条件触发了索引失效规则。
参考来源
MySQL Official Documentation - EXPLAIN Output Format: https://dev.mysql.com/doc/refman/8.0/en/explain-output.html