MySQL 8.0 查询速度慢如何查看执行计划 explain 分析?

文章导读
在 MySQL 8.0 中,查看慢查询执行计划最直接的方法是在 SQL 语句前加上 EXPLAIN 关键字,重点关注 type 和 key 列判断索引使用情况。对于需要实际运行时间的场景,MySQL 8.0.18 及以上版本支持 EXPLAIN ANALYZE 获取实际执行耗时。
📋 目录
  1. A 命令速用版
  2. B 为什么会这样
  3. C 分步处理
  4. D 怎么验证是否生效
  5. E 常见坑
  6. F 常见问题
  7. G 参考来源
A A

在 MySQL 8.0 中,查看慢查询执行计划最直接的方法是在 SQL 语句前加上 EXPLAIN 关键字,重点关注 typekey 列判断索引使用情况。对于需要实际运行时间的场景,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+):

MySQL 8.0 查询速度慢如何查看执行计划 explain 分析?
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';

为什么会这样

MySQL 优化器会根据统计信息选择执行路径,EXPLAIN 用于展示优化器选择的访问路径。

查询速度慢通常是因为优化器选择了全表扫描而不是索引扫描,或者使用了临时表和文件排序。EXPLAIN 输出结果揭示了优化器如何访问表、连接顺序以及是否使用了索引,帮助开发者识别性能瓶颈所在。

分步处理

按以下步骤分析并优化慢查询:

  1. 捕获慢 SQL:检查慢查询日志(slow_query_log),找到执行时间超过阈值的语句。
  2. 执行 EXPLAIN:将捕获的 SQL 语句前加上 EXPLAIN 执行。
  3. 分析关键字段:
    • type:访问类型,至少达到 range 级别,避免 ALL
    • key:实际使用的索引,若为 NULL 则未走索引。
    • rows:预估扫描行数,越少越好。
    • Extra:避免出现 Using filesortUsing temporary
  4. 实施优化:根据 where 条件和 order by 字段添加合适索引。
  5. 回滚提醒:在生产环境添加索引前,建议在测试环境验证,大表加锁操作需避开业务高峰期。

怎么验证是否生效

优化后再次运行 EXPLAIN 命令,对比优化前后的输出结果。

MySQL 8.0 查询速度慢如何查看执行计划 explain 分析?
  • 检查点 1:type 列从 ALL 变为 refrange
  • 检查点 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