v5-0006-adjust-explain-output.patch
text/x-patch
Filename: v5-0006-adjust-explain-output.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v5-0006
Subject: adjust explain output
| File | + | − |
|---|---|---|
| src/backend/commands/explain.c | 13 | 22 |
| src/test/regress/expected/explain.out | 117 | 103 |
| src/test/regress/sql/explain.sql | 2 | 2 |
From b7f7eb1154ec292d7ef464850b98709607c6bd51 Mon Sep 17 00:00:00 2001
From: Tomas Vondra <tomas@vondra.me>
Date: Thu, 26 Mar 2026 01:21:20 +0100
Subject: [PATCH v5 6/6] adjust explain output
- Don't use groups in non-text formats.
- Don't condition fields based on (io_count > 0).
- Print complete labels in non-text formats.
---
src/backend/commands/explain.c | 35 ++--
src/test/regress/expected/explain.out | 220 ++++++++++++++------------
src/test/regress/sql/explain.sql | 4 +-
3 files changed, 132 insertions(+), 127 deletions(-)
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 5933993533e..36ddb5e5852 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -4018,8 +4018,8 @@ print_io_usage(ExplainState *es, IOStats *stats)
if (stats->io_count > 0)
{
ExplainIndentText(es);
- appendStringInfo(es->str, "I/O: stalls=%" PRIu64,
- stats->stall_count);
+ appendStringInfo(es->str, "I/O: count=%" PRIu64 " stalls=%" PRIu64,
+ stats->io_count, stats->stall_count);
appendStringInfo(es->str, " size=%.3f inprogress=%.3f",
(stats->io_nblocks * 1.0 / stats->io_count),
@@ -4030,30 +4030,21 @@ print_io_usage(ExplainState *es, IOStats *stats)
}
else
{
- ExplainOpenGroup("Prefetch", "Prefetch", true, es);
-
- ExplainPropertyFloat("Average Distance", NULL,
+ ExplainPropertyFloat("Average Prefetch Distance", NULL,
(stats->distance_sum * 1.0 / stats->prefetch_count), 3, es);
- ExplainPropertyInteger("Max Distance", NULL,
+ ExplainPropertyInteger("Max Prefetch Distance", NULL,
stats->distance_max, es);
- ExplainPropertyInteger("Capacity", NULL,
+ ExplainPropertyInteger("Prefetch Capacity", NULL,
stats->distance_capacity, es);
- ExplainCloseGroup("Prefetch", "Prefetch", true, es);
-
- if (stats->io_count > 0)
- {
- ExplainOpenGroup("I/O", "I/O", true, es);
-
- ExplainPropertyUInteger("Stalls", NULL,
- stats->stall_count, es);
- ExplainPropertyFloat("Average IO Size", NULL,
- (stats->io_nblocks * 1.0 / stats->io_count), 3, es);
- ExplainPropertyFloat("Average IOs In Progress", NULL,
- (stats->io_in_progress * 1.0 / stats->io_count), 3, es);
-
- ExplainCloseGroup("I/O", "I/O", true, es);
- }
+ ExplainPropertyUInteger("I/O Count", NULL,
+ stats->io_count, es);
+ ExplainPropertyUInteger("I/O Stalls", NULL,
+ stats->stall_count, es);
+ ExplainPropertyFloat("Average I/O Size", NULL,
+ (stats->io_nblocks * 1.0 / Max(1, stats->io_count)), 3, es);
+ ExplainPropertyFloat("Average I/Os In Progress", NULL,
+ (stats->io_in_progress * 1.0 / Max(1, stats->io_count)), 3, es);
}
}
}
diff --git a/src/test/regress/expected/explain.out b/src/test/regress/expected/explain.out
index 97cb7206676..3fa6d838545 100644
--- a/src/test/regress/expected/explain.out
+++ b/src/test/regress/expected/explain.out
@@ -93,112 +93,126 @@ select explain_filter('explain (analyze, buffers, io off, format text) select *
Execution Time: N.N ms
(3 rows)
-select explain_filter('explain (analyze, buffers, io off, format xml) select * from int8_tbl i8');
- explain_filter
---------------------------------------------------------
- <explain xmlns="http://www.postgresql.org/N/explain"> +
- <Query> +
- <Plan> +
- <Node-Type>Seq Scan</Node-Type> +
- <Parallel-Aware>false</Parallel-Aware> +
- <Async-Capable>false</Async-Capable> +
- <Relation-Name>int8_tbl</Relation-Name> +
- <Alias>i8</Alias> +
- <Startup-Cost>N.N</Startup-Cost> +
- <Total-Cost>N.N</Total-Cost> +
- <Plan-Rows>N</Plan-Rows> +
- <Plan-Width>N</Plan-Width> +
- <Actual-Startup-Time>N.N</Actual-Startup-Time> +
- <Actual-Total-Time>N.N</Actual-Total-Time> +
- <Actual-Rows>N.N</Actual-Rows> +
- <Actual-Loops>N</Actual-Loops> +
- <Disabled>false</Disabled> +
- <Shared-Hit-Blocks>N</Shared-Hit-Blocks> +
- <Shared-Read-Blocks>N</Shared-Read-Blocks> +
- <Shared-Dirtied-Blocks>N</Shared-Dirtied-Blocks>+
- <Shared-Written-Blocks>N</Shared-Written-Blocks>+
- <Local-Hit-Blocks>N</Local-Hit-Blocks> +
- <Local-Read-Blocks>N</Local-Read-Blocks> +
- <Local-Dirtied-Blocks>N</Local-Dirtied-Blocks> +
- <Local-Written-Blocks>N</Local-Written-Blocks> +
- <Temp-Read-Blocks>N</Temp-Read-Blocks> +
- <Temp-Written-Blocks>N</Temp-Written-Blocks> +
- </Plan> +
- <Planning> +
- <Shared-Hit-Blocks>N</Shared-Hit-Blocks> +
- <Shared-Read-Blocks>N</Shared-Read-Blocks> +
- <Shared-Dirtied-Blocks>N</Shared-Dirtied-Blocks>+
- <Shared-Written-Blocks>N</Shared-Written-Blocks>+
- <Local-Hit-Blocks>N</Local-Hit-Blocks> +
- <Local-Read-Blocks>N</Local-Read-Blocks> +
- <Local-Dirtied-Blocks>N</Local-Dirtied-Blocks> +
- <Local-Written-Blocks>N</Local-Written-Blocks> +
- <Temp-Read-Blocks>N</Temp-Read-Blocks> +
- <Temp-Written-Blocks>N</Temp-Written-Blocks> +
- </Planning> +
- <Planning-Time>N.N</Planning-Time> +
- <Triggers> +
- </Triggers> +
- <Execution-Time>N.N</Execution-Time> +
- </Query> +
+select explain_filter('explain (analyze, buffers, io, format xml) select * from int8_tbl i8');
+ explain_filter
+------------------------------------------------------------------
+ <explain xmlns="http://www.postgresql.org/N/explain"> +
+ <Query> +
+ <Plan> +
+ <Node-Type>Seq Scan</Node-Type> +
+ <Parallel-Aware>false</Parallel-Aware> +
+ <Async-Capable>false</Async-Capable> +
+ <Relation-Name>int8_tbl</Relation-Name> +
+ <Alias>i8</Alias> +
+ <Startup-Cost>N.N</Startup-Cost> +
+ <Total-Cost>N.N</Total-Cost> +
+ <Plan-Rows>N</Plan-Rows> +
+ <Plan-Width>N</Plan-Width> +
+ <Actual-Startup-Time>N.N</Actual-Startup-Time> +
+ <Actual-Total-Time>N.N</Actual-Total-Time> +
+ <Actual-Rows>N.N</Actual-Rows> +
+ <Actual-Loops>N</Actual-Loops> +
+ <Disabled>false</Disabled> +
+ <Average-Prefetch-Distance>N.N</Average-Prefetch-Distance>+
+ <Max-Prefetch-Distance>N</Max-Prefetch-Distance> +
+ <Prefetch-Capacity>N</Prefetch-Capacity> +
+ <I-O-Count>N</I-O-Count> +
+ <I-O-Stalls>N</I-O-Stalls> +
+ <Average-I-O-Size>N.N</Average-I-O-Size> +
+ <Average-I-Os-In-Progress>N.N</Average-I-Os-In-Progress> +
+ <Shared-Hit-Blocks>N</Shared-Hit-Blocks> +
+ <Shared-Read-Blocks>N</Shared-Read-Blocks> +
+ <Shared-Dirtied-Blocks>N</Shared-Dirtied-Blocks> +
+ <Shared-Written-Blocks>N</Shared-Written-Blocks> +
+ <Local-Hit-Blocks>N</Local-Hit-Blocks> +
+ <Local-Read-Blocks>N</Local-Read-Blocks> +
+ <Local-Dirtied-Blocks>N</Local-Dirtied-Blocks> +
+ <Local-Written-Blocks>N</Local-Written-Blocks> +
+ <Temp-Read-Blocks>N</Temp-Read-Blocks> +
+ <Temp-Written-Blocks>N</Temp-Written-Blocks> +
+ </Plan> +
+ <Planning> +
+ <Shared-Hit-Blocks>N</Shared-Hit-Blocks> +
+ <Shared-Read-Blocks>N</Shared-Read-Blocks> +
+ <Shared-Dirtied-Blocks>N</Shared-Dirtied-Blocks> +
+ <Shared-Written-Blocks>N</Shared-Written-Blocks> +
+ <Local-Hit-Blocks>N</Local-Hit-Blocks> +
+ <Local-Read-Blocks>N</Local-Read-Blocks> +
+ <Local-Dirtied-Blocks>N</Local-Dirtied-Blocks> +
+ <Local-Written-Blocks>N</Local-Written-Blocks> +
+ <Temp-Read-Blocks>N</Temp-Read-Blocks> +
+ <Temp-Written-Blocks>N</Temp-Written-Blocks> +
+ </Planning> +
+ <Planning-Time>N.N</Planning-Time> +
+ <Triggers> +
+ </Triggers> +
+ <Execution-Time>N.N</Execution-Time> +
+ </Query> +
</explain>
(1 row)
-select explain_filter('explain (analyze, serialize, buffers, io off, format yaml) select * from int8_tbl i8');
- explain_filter
--------------------------------
- - Plan: +
- Node Type: "Seq Scan" +
- Parallel Aware: false +
- Async Capable: false +
- Relation Name: "int8_tbl"+
- Alias: "i8" +
- Startup Cost: N.N +
- Total Cost: N.N +
- Plan Rows: N +
- Plan Width: N +
- Actual Startup Time: N.N +
- Actual Total Time: N.N +
- Actual Rows: N.N +
- Actual Loops: N +
- Disabled: false +
- Shared Hit Blocks: N +
- Shared Read Blocks: N +
- Shared Dirtied Blocks: N +
- Shared Written Blocks: N +
- Local Hit Blocks: N +
- Local Read Blocks: N +
- Local Dirtied Blocks: N +
- Local Written Blocks: N +
- Temp Read Blocks: N +
- Temp Written Blocks: N +
- Planning: +
- Shared Hit Blocks: N +
- Shared Read Blocks: N +
- Shared Dirtied Blocks: N +
- Shared Written Blocks: N +
- Local Hit Blocks: N +
- Local Read Blocks: N +
- Local Dirtied Blocks: N +
- Local Written Blocks: N +
- Temp Read Blocks: N +
- Temp Written Blocks: N +
- Planning Time: N.N +
- Triggers: +
- Serialization: +
- Time: N.N +
- Output Volume: N +
- Format: "text" +
- Shared Hit Blocks: N +
- Shared Read Blocks: N +
- Shared Dirtied Blocks: N +
- Shared Written Blocks: N +
- Local Hit Blocks: N +
- Local Read Blocks: N +
- Local Dirtied Blocks: N +
- Local Written Blocks: N +
- Temp Read Blocks: N +
- Temp Written Blocks: N +
+select explain_filter('explain (analyze, serialize, buffers, io, format yaml) select * from int8_tbl i8');
+ explain_filter
+------------------------------------
+ - Plan: +
+ Node Type: "Seq Scan" +
+ Parallel Aware: false +
+ Async Capable: false +
+ Relation Name: "int8_tbl" +
+ Alias: "i8" +
+ Startup Cost: N.N +
+ Total Cost: N.N +
+ Plan Rows: N +
+ Plan Width: N +
+ Actual Startup Time: N.N +
+ Actual Total Time: N.N +
+ Actual Rows: N.N +
+ Actual Loops: N +
+ Disabled: false +
+ Average Prefetch Distance: N.N+
+ Max Prefetch Distance: N +
+ Prefetch Capacity: N +
+ I/O Count: N +
+ I/O Stalls: N +
+ Average I/O Size: N.N +
+ Average I/Os In Progress: N.N +
+ Shared Hit Blocks: N +
+ Shared Read Blocks: N +
+ Shared Dirtied Blocks: N +
+ Shared Written Blocks: N +
+ Local Hit Blocks: N +
+ Local Read Blocks: N +
+ Local Dirtied Blocks: N +
+ Local Written Blocks: N +
+ Temp Read Blocks: N +
+ Temp Written Blocks: N +
+ Planning: +
+ Shared Hit Blocks: N +
+ Shared Read Blocks: N +
+ Shared Dirtied Blocks: N +
+ Shared Written Blocks: N +
+ Local Hit Blocks: N +
+ Local Read Blocks: N +
+ Local Dirtied Blocks: N +
+ Local Written Blocks: N +
+ Temp Read Blocks: N +
+ Temp Written Blocks: N +
+ Planning Time: N.N +
+ Triggers: +
+ Serialization: +
+ Time: N.N +
+ Output Volume: N +
+ Format: "text" +
+ Shared Hit Blocks: N +
+ Shared Read Blocks: N +
+ Shared Dirtied Blocks: N +
+ Shared Written Blocks: N +
+ Local Hit Blocks: N +
+ Local Read Blocks: N +
+ Local Dirtied Blocks: N +
+ Local Written Blocks: N +
+ Temp Read Blocks: N +
+ Temp Written Blocks: N +
Execution Time: N.N
(1 row)
diff --git a/src/test/regress/sql/explain.sql b/src/test/regress/sql/explain.sql
index 5ee453a0a96..7acd52da0db 100644
--- a/src/test/regress/sql/explain.sql
+++ b/src/test/regress/sql/explain.sql
@@ -66,8 +66,8 @@ select explain_filter('explain select * from int8_tbl i8');
select explain_filter('explain (analyze, buffers off, io off) select * from int8_tbl i8');
select explain_filter('explain (analyze, buffers off, io off, verbose) select * from int8_tbl i8');
select explain_filter('explain (analyze, buffers, io off, format text) select * from int8_tbl i8');
-select explain_filter('explain (analyze, buffers, io off, format xml) select * from int8_tbl i8');
-select explain_filter('explain (analyze, serialize, buffers, io off, format yaml) select * from int8_tbl i8');
+select explain_filter('explain (analyze, buffers, io, format xml) select * from int8_tbl i8');
+select explain_filter('explain (analyze, serialize, buffers, io, format yaml) select * from int8_tbl i8');
select explain_filter('explain (buffers, format text) select * from int8_tbl i8');
select explain_filter('explain (buffers, format json) select * from int8_tbl i8');
--
2.53.0