EXPLAIN FORMAT=JSON 是嵌套树状结构,非传统平面表格,需按 query_block.select_id 定层级、table.access_type 定效率、cost_info 各子字段定瓶颈,不可直接套用行式解析逻辑。

EXPLAIN FORMAT=JSON 输出天然适合自动化分析,但前提是理解它的结构边界和字段语义——它不是“更详细的传统 EXPLAIN”,而是完全不同的数据模型。
为什么不能直接用传统 EXPLAIN 的解析逻辑处理 JSON 输出
传统 EXPLAIN 是平面表格,每行对应一个表访问;而 EXPLAIN FORMAT=JSON 是嵌套树状结构,一个 query_block 可能包含 nested_loop、table、grouping_operation 等子节点,层级由 SQL 语义(如 JOIN、子查询、GROUP BY)决定。直接按行解析 JSON 字符串会漏掉嵌套关系,比如误判子查询成本或忽略物化临时表的开销。
- 看到
"select_type": "DERIVED"时,对应 JSON 中是query_block下的materialized_from_subquery字段,而非独立table节点 -
"type": "index_merge"在传统输出中是一行,但在 JSON 中会拆成多个table子节点,每个带自己的access_type和key - MySQL 8.3+ 引入
explain_json_format_version=2后,JSON 结构与FORMAT=TREE完全对齐,但旧版(v1)字段命名和嵌套深度不一致,脚本需做版本判断
提取关键指标必须定位到正确路径
自动化脚本若只查顶层 query_block.cost_info.query_cost,会低估含子查询或 UNION 的总成本。真实总成本需递归汇总所有 query_block 和子节点的 cost_info。
- 扫描行数不能只看
table.rows:它只是预估值,且仅对最内层表有效;应优先取table.cost_info.read_cost(I/O 成本)和eval_cost(CPU 成本)组合评估 - 索引使用状态要交叉验证:
table.key非空 ≠ 有效利用,需同时检查table.key_len是否匹配复合索引最左前缀,以及table.access_type是否为ref或更高 - 是否触发临时表或文件排序,传统
Extra字段在 JSON 中分散在table.using_temporary_table、query_block.sorting_operation等布尔字段里,漏查任一都可能误判
兼容 MySQL 5.7–8.4 的 JSON 解析要点
MySQL 5.7 开始支持 FORMAT=JSON,但字段粒度差异大:5.7 缺少 cost_info 下的 prefix_cost,8.0+ 才有 ordering_operation 显式标记排序操作。硬编码字段路径会导致低版本解析失败。
- 必须先读取
query_block.select_id判断是否存在多查询块,再决定是否遍历query_block.nested_loop或query_block.union_result - 对
table.access_type做枚举校验时,需兼容 5.7 的ALL/range和 8.3+ 新增的index_rowid_intersection等类型 - 避免依赖
message字段:它在某些场景下为空(如简单查询),且内容非结构化(例:"No tables used"),无法用于逻辑判断
真正稳定的自动化分析,不是解析整个 JSON,而是聚焦三个锚点:query_block.select_id 定层级、table.access_type 定效率、cost_info 下各子字段定瓶颈来源。其他字段随 MySQL 版本浮动,只作辅助验证。


















