EXPLAIN 的输出格式是什么
MySQL 8.0 的 EXPLAIN 除默认表格外还支持 FORMAT=TREE 与 FORMAT=JSON。TREE 把计划渲染成树形,8.0.16 起每个节点带估算成本与行数,阅读顺序基本等于实际访问顺序;JSON 输出结构化字段(query_cost、key_length、used_key_parts 等),适合脚本解析与自动化对比。EXPLAIN ANALYZE 输出的也是 TREE 形态,但带真实耗时与实际行数,用来验证估算是否靠谱。PostgreSQL 的对应能力是 EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS)。
基本信息
| 适用平台 | MySQL 8.0;TREE 自 5.7.8 可用,成本信息自 8.0.16 起 |
|---|---|
| 语法 | EXPLAIN FORMAT=TREE 语句、EXPLAIN FORMAT=JSON 语句 |
| 实测格式 | EXPLAIN ANALYZE(8.0.18+),输出 TREE 形态并附带实测值 |
| PostgreSQL 对应 | EXPLAIN (FORMAT JSON, ANALYZE, BUFFERS) 语句 |
| 成本口径 | cost 是优化器内部单位,不是时间,只适合同实例横向比较 |
典型使用场景
- 对比两种写法的估算成本,判断改写是否值得
- 把 JSON 计划纳入 CI,做执行计划的回归比对
- 阅读复杂多表连接的访问顺序与算子嵌套
- 找出排序、临时表这类代价高的算子出现在哪一层
- 配合 EXPLAIN ANALYZE 定位估算行数与实际行数偏差大的节点
TREE 格式
TREE 格式
EXPLAIN FORMAT=TREE
SELECT o.id, o.total
FROM orders o
JOIN users u ON u.id = o.user_id
WHERE u.city = 'shanghai'
ORDER BY o.created_at DESC
LIMIT 10;
# 输出形如(8.0.16 起带 cost 与 rows):
# -> Limit: 10 row(s)
# -> Sort: o.created_at DESC, limit input to 10 row(s) per chunk
# -> Stream results
# -> Nested loop inner join
# -> Filter: (u.city = 'shanghai')JSON 格式与关键字段
JSON 格式与关键字段
EXPLAIN FORMAT=JSON SELECT * FROM orders WHERE user_id = 100;
# query_block.cost_info.query_cost 整条语句的估算成本
# table.access_type 访问方式:ALL / ref / range / index
# table.key 实际选用的索引
# table.key_length 用到的索引前缀字节数
# table.used_key_parts 命中的索引列
# table.rows_examined_per_scan 每次扫描的估算行数几种输出格式怎么选
| 格式 | 特点 | 适用判断 |
|---|---|---|
| 默认表格 | 一行一张表,字段横向排列 | 快速人工检查 type / key / rows |
| FORMAT=TREE | 树形,8.0.16+ 带成本 | 看连接顺序与算子嵌套 |
| FORMAT=JSON | 字段最全且可解析 | 自动化对比、CI 回归 |
| EXPLAIN ANALYZE | TREE 形态 + 实测耗时与行数 | 定位估算偏差 |
TREE 里的 cost 是优化器内部单位,只能在同一实例上比较不同写法的相对大小,绝对值与毫秒没有换算关系。
EXPLAIN ANALYZE 会真正执行语句,只是把结果丢弃:对 UPDATE / DELETE 使用时务必先改成等价的 SELECT,或包在事务里回滚,否则会直接改数据。
用 EXPLAIN 输出做自动化断言时要锁定数据库小版本:成本数字、节点命名与字段顺序都可能随版本变化,断言写得过死会在升级后集体失败。