PostgreSQL 16 JSON 计划检查
读取一至两份 PostgreSQL 16 JSON 执行计划,保留原始树、Workers 与数值写法,解释循环和并行口径并按位置比较。
粘贴或选择 PostgreSQL 16 导出的 JSON 数组。纯文本计划需明确手动整理或导出 JSON;工具不会执行查询。
使用已有的 PostgreSQL 16 EXPLAIN (FORMAT JSON) 导出。导出或分析查询仍由你的数据库流程完成。
尚无结果
开始之前
读取一至两份 PostgreSQL 16 JSON 执行计划,保留原始树、Workers 与数值写法,解释循环和并行口径并按位置比较。
如何使用
- 确认原始导出来自 PostgreSQL 16,并保留 JSON 数组。
- 给主计划选择粘贴或文件;可选启用对照并独立选择来源。
- 阅读完整树、数值词法、循环与并行范围以及位置对比。
- 下载原始计划、版本封装、完整报告与 CSV;复制保留完整正文。
支持范围与限制
主计划与对照的原始 UTF-8 字节合计不超过 1 MiB;单个文件名最多 512 UTF-8 字节,MIME 标签最多 128。容量与元数据在读取文件前核对;原始字节、角色、文件名、字节数及 SHA256 全部保留。
每份计划 1–32 个 statement、最多 2048 个 operator,operator 深度最多 32,每份最多 256 个 Workers 记录。版本封装与全部源计划合计最多 100000 个 JSON 值节点,封装根深度为 0、最多 128;单个源数组根在封装深度 2。
仅接收 EXPLAIN FORMAT JSON 数组,不解析文本计划、不执行 SQL。数值必须有限、非负、可无损表示;重复键、BOM、负零及不安全整数拒绝。
operator 节点的 Actual Startup Time、Actual Total Time、Actual Rows、Actual Loops 如出现,必须四者齐全;用于循环乘积的时间、行数与 loops 须用普通十进制写法,指数写法拒绝。Workers 的原始字段保留并检查已提供数值。TIMING OFF 等缺少实际时间的部分 Actual 记录当前拒绝。
cost 是规划器单位;Actual 时间和行数按循环平均。报告用精确十进制字符串乘 loops,时间包含子节点并可能有并行重叠,不求相加总时间;buffers 不乘 loops。
两份计划只按相同 statement 和子节点位置比较,标记新增、删除和 operator 改变;不推断节点身份或优化成功。完整所有文件与复制文本合计最多 16 MiB。
主计划与可选对照计划各自选择粘贴或一个 JSON 文件;只有显式启用的角色和模式会读取。文件同名不会改变角色。显式版本仅支持 PostgreSQL 16。
TEXT 计划需要在 PostgreSQL 16 另行导出 FORMAT JSON;本工具不执行 SQL、不连接数据库,也不能据此确认优化成功或解释全部客户端等待时间。历史问题的 2015 TEXT 测量只作为需求背景;界面样例使用已保存的受控 PostgreSQL 16.15 JSON 导出。
10 秒完整绝对期限从元数据、参数验证和文件读取之前开始,贯穿 Worker 加载、处理和发布。取消、超时或源变更清除旧报告、表格与下载;保留同一份完整源可重新运行。
完整报告、CSV、原始计划、版本封装及复制正文合计最多 16 MiB;大型序列化前预留容量,typed 报告/表格另限 16 MiB,物理与 typed 数据运输合计限 32 MiB,数字路径累计限 8 MiB。超限原子拒绝。
操作示例
示例输入
[{"Plan":{"Node Type":"Function Scan","Parallel Aware":false,"Async Capable":false,"Function Name":"generate_series","Schema":"pg_catalog","Alias":"a","Startup Cost":0,"Total Cost":0.18,"Plan Rows":1,"Plan Width":4,"Output":["i"],"Function Call":"generate_series(1, 12)","Filter":"((a.i % 2) = 0)","Shared Hit Blocks":0,"Shared Read Blocks":0,"Shared Dirtied Blocks":0,"Shared Written Blocks":0,"Local Hit Blocks":0,"Local Read Blocks":0,"Local Dirtied Blocks":0,"Local Written Blocks":0,"Temp Read Blocks":0,"Temp Written Blocks":0},"Planning":{"Shared Hit Blocks":5,"Shared Read Blocks":0,"Shared Dirtied Blocks":0,"Shared Written Blocks":0,"Local Hit Blocks":0,"Local Read Blocks":0,"Local Dirtied Blocks":0,"Local Written Blocks":0,"Temp Read Blocks":0,"Temp Written Blocks":0}}]示例参数
{"serverMajor":"16","comparisonEnabled":false,"primarySourceMode":"paste"}示例输出
{
"schema": "neatbo-pg-plan/1",
"serverMajor": 16,
"comparisonStrategy": "same-statement-child-position; no identity or optimization inference",
"costSemantics": "planner cost units, not milliseconds",
"executionSemantics": "measured database execution; excludes client delivery and rendering; node times inclusive and per-loop",
"numericLexemes": [
{
"pointer": "/serverMajor",
"lexeme": "16",
"value": 16
},
{
"pointer": "/plans/0/0/Plan/Startup Cost",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Plan/Total Cost",
"lexeme": "0.18",
"value": 0.18
},
{
"pointer": "/plans/0/0/Plan/Plan Rows",
"lexeme": "1",
"value": 1
},
{
"pointer": "/plans/0/0/Plan/Plan Width",
"lexeme": "4",
"value": 4
},
{
"pointer": "/plans/0/0/Plan/Shared Hit Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Plan/Shared Read Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Plan/Shared Dirtied Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Plan/Shared Written Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Plan/Local Hit Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Plan/Local Read Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Plan/Local Dirtied Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Plan/Local Written Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Plan/Temp Read Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Plan/Temp Written Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Planning/Shared Hit Blocks",
"lexeme": "5",
"value": 5
},
{
"pointer": "/plans/0/0/Planning/Shared Read Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Planning/Shared Dirtied Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Planning/Shared Written Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Planning/Local Hit Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Planning/Local Read Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Planning/Local Dirtied Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Planning/Local Written Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Planning/Temp Read Blocks",
"lexeme": "0",
"value": 0
},
{
"pointer": "/plans/0/0/Planning/Temp Written Blocks",
"lexeme": "0",
"value": 0
}
],
"plans": [
{
"planIndex": 0,
"statementCount": 1,
"nodeCount": 1,
"workerCount": 0,
"statements": [
{
"Plan": {
"Node Type": "Function Scan",
"Parallel Aware": false,
"Async Capable": false,
"Function Name": "generate_series",
"Schema": "pg_catalog",
"Alias": "a",
"Startup Cost": 0,
"Total Cost": 0.18,
"Plan Rows": 1,
"Plan Width": 4,
"Output": [
"i"
],
"Function Call": "generate_series(1, 12)",
"Filter": "((a.i % 2) = 0)",
"Shared Hit Blocks": 0,
"Shared Read Blocks": 0,
"Shared Dirtied Blocks": 0,
"Shared Written Blocks": 0,
"Local Hit Blocks": 0,
"Local Read Blocks": 0,
"Local Dirtied Blocks": 0,
"Local Written Blocks": 0,
"Temp Read Blocks": 0,
"Temp Written Blocks": 0
},
"Planning": {
"Shared Hit Blocks": 5,
"Shared Read Blocks": 0,
"Shared Dirtied Blocks": 0,
"Shared Written Blocks": 0,
"Local Hit Blocks": 0,
"Local Read Blocks": 0,
"Local Dirtied Blocks": 0,
"Local Written Blocks": 0,
"Temp Read Blocks": 0,
"Temp Written Blocks": 0
}
}
],
"nodes": [
{
"index": 0,
"statementIndex": 0,
"path": "/plans/0/0/Plan",
"parent": null,
"depth": 0,
"operator": "Function Scan",
"source": {
"Node Type": "Function Scan",
"Parallel Aware": false,
"Async Capable": false,
"Function Name": "generate_series",
"Schema": "pg_catalog",
"Alias": "a",
"Startup Cost": 0,
"Total Cost": 0.18,
"Plan Rows": 1,
"Plan Width": 4,
"Output": [
"i"
],
"Function Call": "generate_series(1, 12)",
"Filter": "((a.i % 2) = 0)",
"Shared Hit Blocks": 0,
"Shared Read Blocks": 0,
"Shared Dirtied Blocks": 0,
"Shared Written Blocks": 0,
"Local Hit Blocks": 0,
"Local Read Blocks": 0,
"Local Dirtied Blocks": 0,
"Local Written Blocks": 0,
"Temp Read Blocks": 0,
"Temp Written Blocks": 0
},
"metrics": {
"Startup Cost": {
"value": 0,
"lexeme": "0",
"unit": "planner-cost-unit"
},
"Total Cost": {
"value": 0.18,
"lexeme": "0.18",
"unit": "planner-cost-unit"
},
"Plan Rows": {
"value": 1,
"lexeme": "1",
"unit": "count"
},
"Plan Width": {
"value": 4,
"lexeme": "4",
"unit": "estimated-bytes-per-row"
},
"Shared Hit Blocks": {
"value": 0,
"lexeme": "0",
"unit": "blocks"
},
"Shared Read Blocks": {
"value": 0,
"lexeme": "0",
"unit": "blocks"
},
"Shared Dirtied Blocks": {
"value": 0,
"lexeme": "0",
"unit": "blocks"
},
"Shared Written Blocks": {
"value": 0,
"lexeme": "0",
"unit": "blocks"
},
"Local Hit Blocks": {
"value": 0,
"lexeme": "0",
"unit": "blocks"
},
"Local Read Blocks": {
"value": 0,
"lexeme": "0",
"unit": "blocks"
},
"Local Dirtied Blocks": {
"value": 0,
"lexeme": "0",
"unit": "blocks"
},
"Local Written Blocks": {
"value": 0,
"lexeme": "0",
"unit": "blocks"
},
"Temp Read Blocks": {
"value": 0,
"lexeme": "0",
"unit": "blocks"
},
"Temp Written Blocks": {
"value": 0,
"lexeme": "0",
"unit": "blocks"
}
},
"actualPresent": false,
"parallelScope": false,
"inclusiveAverageTimeMs": null,
"timeAcrossLoopsMs": null,
"rowsAcrossLoops": null,
"timeSemantics": "inclusive-per-loop; children-overlap; not-additive",
"buffersSemantics": "reported-inclusive-node-counts; not-multiplied-by-loops"
}
]
}
],
"comparisons": [],
"sourceInputs": [
{
"role": "primary",
"kind": "paste",
"name": "primary-pasted.json",
"mime": "application/json",
"bytes": 783,
"sha256": "26a4039336d776def17a9ad9cab3e8bcc63d7dd992378a72e12d92b09357b9da"
}
],
"inputBytes": 783,
"sourceCount": 1,
"operatorCount": 1,
"statementCount": 1,
"comparisonCount": 0
}
出现问题时
文本计划请重新导出 JSON;版本或 Actual 字段不完整时先确认来源。超预算可拆分 statement。保留原件后修正并重试,不返回部分计划。
常见问题
为何不能把各节点时间相加?
节点时间包含子节点,平行参与者也可能重叠。相加可能重复计算数据库工作。
执行计划能解释客户端 30 秒全部用时吗?
不能。数据库测得执行阶段不包括结果传送和客户端渲染;本工具保留这一区别,不断言数据库已无需优化。