在 MySQL 8.0 中,查看慢查询执行计划最直接的方法是在 SQL 语句前加上 EXPLAIN 关键字,重点关注 type 和 key 列判断索引使用情况。对于需要实际运行时间的场景,MySQL 8.0.18 及以上版本支持 EXPLAIN ANALYZE 获取实际执行耗时。
先说结论:使用 EXPLAIN 定位索引缺失或全表扫描,结合慢查询日志找到具体 SQL。
- 先定位:通过慢查询日志或 performance_schema 捕获耗时 SQL 语句。
- 先做:对可疑 SQL 执行 EXPLAIN 分析执行计划,检查是否走索引。
- 再验证:优化后再次执行 EXPLAIN 对比 type 列变化,并观察业务响应时间。
命令速用版
在 MySQL 命令行或客户端工具中,直接在 SELECT 语句前添加解释命令。
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
如果需要查看实际执行耗时(MySQL 8.0.18+):
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';
为什么会这样
MySQL 优化器会根据统计信息选择执行路径,EXPLAIN 用于展示优化器选择的访问路径。
查询速度慢通常是因为优化器选择了全表扫描而不是索引扫描,或者使用了临时表和文件排序。EXPLAIN 输出结果揭示了优化器如何访问表、连接顺序以及是否使用了索引,帮助开发者识别性能瓶颈所在。
分步处理
按以下步骤分析并优化慢查询:
- 捕获慢 SQL:检查慢查询日志(slow_query_log),找到执行时间超过阈值的语句。
- 执行 EXPLAIN:将捕获的 SQL 语句前加上
EXPLAIN执行。 - 分析关键字段:
type:访问类型,至少达到range级别,避免ALL。key:实际使用的索引,若为 NULL 则未走索引。rows:预估扫描行数,越少越好。Extra:避免出现Using filesort或Using temporary。
- 实施优化:根据
where条件和order by字段添加合适索引。 - 回滚提醒:在生产环境添加索引前,建议在测试环境验证,大表加锁操作需避开业务高峰期。
怎么验证是否生效
优化后再次运行 EXPLAIN 命令,对比优化前后的输出结果。
- 检查点 1:
type列从ALL变为ref或range。 - 检查点 2:
key列显示新创建的索引名称。 - 检查点 3:
rows列数值显著下降。 - 业务验证:在应用侧观察接口响应时间或数据库监控中的查询耗时是否降低。
常见坑
- 隐式类型转换:字符串字段未加引号会导致索引失效,EXPLAIN 中 type 可能显示 ALL。
- 最左前缀原则:联合索引未按顺序使用会导致后续列索引失效。
- 函数操作:对索引列使用函数或计算会导致索引无法使用。
- 统计信息过期:如果表数据变化大,执行
ANALYZE TABLE更新统计信息,否则 EXPLAIN 预估行数可能不准。
常见问题
EXPLAIN 和 EXPLAIN ANALYZE 有什么区别?
EXPLAIN 仅展示优化器预估的执行计划,不实际执行 SQL;EXPLAIN ANALYZE 会实际执行 SQL 并显示实际耗时和迭代器信息。
type 列哪些值代表性能较好?
性能从好到坏依次为 system、const、eq_ref、ref、range、index、ALL,建议至少优化到 range 级别。
Extra 列出现 Using filesort 一定要优化吗?
不一定,如果数据量小或排序开销可接受可以忽略,但大数据量下建议通过索引消除文件排序。
参考来源
- MySQL Official Documentation, "EXPLAIN Statement", https://dev.mysql.com/doc/refman/8.0/en/explain.html