EXPLAIN ANALYZE 的价值
EXPLAIN 只给出估算的执行计划,EXPLAIN ANALYZE(MySQL 8.0.18+)会真正执行语句,并在计划树上标注每一步的实际耗时、实际返回行数与循环次数,把估算与实际摆在一起对比。估算行数与实际行数差出几个数量级,通常就是选错索引或统计信息失真的信号,这是定位 SQL 性能问题最有效的闭环。
基本信息
| 适用平台 | MySQL 8.0.18+、PostgreSQL、Oracle |
|---|---|
| 语法 | EXPLAIN ANALYZE SELECT ... |
| 输出形式 | TREE 格式计划 + actual time / rows / loops |
| 关键对比 | 估算 rows 与实际 rows 的比值 |
| 配套数据源 | 慢日志、performance_schema.events_statements_summary_by_digest |
典型使用场景
- 慢查询语句改造前后对比,用实际耗时验证优化是否有效
- 确认优化器是否选错索引,估算行数与实际行数严重偏离
- 评估关联顺序与驱动表选择是否合理
- 大表加索引前后做验证,避免上线后发现效果不符预期
- 排查排序与临时表:确认是否出现 filesort 或落盘临时表
诊断示例
诊断示例
-- 真实执行并输出各节点的实际耗时与行数
EXPLAIN ANALYZE
SELECT o.id, o.amount, u.name
FROM orders o JOIN users u ON u.id = o.user_id
WHERE o.status = 'paid' AND o.created_at >= '2026-09-01'
ORDER BY o.created_at DESC LIMIT 50;
-- 只看估算计划(不执行),对比差异
EXPLAIN FORMAT = TREE SELECT ...;
-- 从慢日志里找候选语句
SELECT start_time, query_time, rows_examined, rows_sent, sql_text
FROM mysql.slow_log ORDER BY query_time DESC LIMIT 10;
-- 统计信息失真时先刷新
ANALYZE TABLE appdb.orders;输出逐列读法
| 字段 | 含义 | 正常与异常 |
|---|---|---|
| actual time | 该节点实际耗时区间(首行到末行) | 某一层占比极高说明瓶颈在该步 |
| rows | 该节点实际返回行数 | 与估算相差巨大说明统计信息失真 |
| loops | 该节点被执行次数 | 嵌套循环次数多时总耗时需乘以 loops |
| cost | 优化器估算代价,仅存在于估算计划 | 只作参考,不代表真实耗时 |
| filtered | 条件过滤后剩余行比例 | 比例极低说明扫描了大量无用行 |
对比指标要一次看全:计划末尾的总耗时、每一步的 actual time 与 rows、以及估算行数三者的关系,才能判断是索引问题、统计信息问题还是数据分布问题。
EXPLAIN ANALYZE 会真执行语句并产生真实副作用:只在 SELECT 上使用,DML 语句要先改成对应查询再分析,或在测试库验证。