summaryrefslogtreecommitdiff
path: root/src/backend/commands/explain.c
diff options
context:
space:
mode:
authorDavid Rowley <drowley@postgresql.org>2020-06-19 17:24:27 +1200
committerDavid Rowley <drowley@postgresql.org>2020-06-19 17:24:27 +1200
commit9bdb300dedf086cc54edf740088208e6b24307ef (patch)
tree62d1699e8bd93fcd6ce59b16d5fe4bfa6c09c4d7 /src/backend/commands/explain.c
parentf219167910ad33dfd8f1b0bba15323d71a91c4e9 (diff)
downloadpostgresql-9bdb300dedf086cc54edf740088208e6b24307ef.tar.gz
Fix EXPLAIN ANALYZE for parallel HashAgg plans
Since 1f39bce02, HashAgg nodes have had the ability to spill to disk when memory consumption exceeds work_mem. That commit added new properties to EXPLAIN ANALYZE to show the maximum memory usage and disk usage, however, it didn't quite go as far as showing that information for parallel workers. Since workers may have experienced something very different from the main process, we should show this information per worker, as is done in Sort. Reviewed-by: Justin Pryzby Reviewed-by: Jeff Davis Discussion: https://postgr.es/m/CAApHDvpEKbfZa18mM1TD7qV6PG+w97pwCWq5tVD0dX7e11gRJw@mail.gmail.com Backpatch-through: 13, where the hashagg spilling code was added.
Diffstat (limited to 'src/backend/commands/explain.c')
-rw-r--r--src/backend/commands/explain.c110
1 files changed, 96 insertions, 14 deletions
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 9092b4b309..67bdcb2b27 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -3051,29 +3051,111 @@ show_hashagg_info(AggState *aggstate, ExplainState *es)
Agg *agg = (Agg *) aggstate->ss.ps.plan;
int64 memPeakKb = (aggstate->hash_mem_peak + 1023) / 1024;
- Assert(IsA(aggstate, AggState));
-
if (agg->aggstrategy != AGG_HASHED &&
agg->aggstrategy != AGG_MIXED)
return;
- if (es->costs && aggstate->hash_planned_partitions > 0)
+ if (es->format != EXPLAIN_FORMAT_TEXT)
{
- ExplainPropertyInteger("Planned Partitions", NULL,
- aggstate->hash_planned_partitions, es);
+
+ if (es->costs && aggstate->hash_planned_partitions > 0)
+ {
+ ExplainPropertyInteger("Planned Partitions", NULL,
+ aggstate->hash_planned_partitions, es);
+ }
+
+ if (!es->analyze)
+ return;
+
+ /* EXPLAIN ANALYZE */
+ ExplainPropertyInteger("Peak Memory Usage", "kB", memPeakKb, es);
+ if (aggstate->hash_batches_used > 0)
+ {
+ ExplainPropertyInteger("Disk Usage", "kB",
+ aggstate->hash_disk_used, es);
+ ExplainPropertyInteger("HashAgg Batches", NULL,
+ aggstate->hash_batches_used, es);
+ }
}
+ else
+ {
+ bool gotone = false;
- if (!es->analyze)
- return;
+ if (es->costs && aggstate->hash_planned_partitions > 0)
+ {
+ ExplainIndentText(es);
+ appendStringInfo(es->str, "Planned Partitions: %d",
+ aggstate->hash_planned_partitions);
+ gotone = true;
+ }
+
+ if (!es->analyze)
+ {
+ if (gotone)
+ appendStringInfoChar(es->str, '\n');
+ return;
+ }
+
+ if (!gotone)
+ ExplainIndentText(es);
+ else
+ appendStringInfoString(es->str, " ");
+
+ appendStringInfo(es->str, "Peak Memory Usage: " INT64_FORMAT " kB",
+ memPeakKb);
- /* EXPLAIN ANALYZE */
- ExplainPropertyInteger("Peak Memory Usage", "kB", memPeakKb, es);
- if (aggstate->hash_batches_used > 0)
+ if (aggstate->hash_batches_used > 0)
+ appendStringInfo(es->str, " Disk Usage: " UINT64_FORMAT " kB HashAgg Batches: %d",
+ aggstate->hash_disk_used,
+ aggstate->hash_batches_used);
+ appendStringInfoChar(es->str, '\n');
+ }
+
+ /* Display stats for each parallel worker */
+ if (es->analyze && aggstate->shared_info != NULL)
{
- ExplainPropertyInteger("Disk Usage", "kB",
- aggstate->hash_disk_used, es);
- ExplainPropertyInteger("HashAgg Batches", NULL,
- aggstate->hash_batches_used, es);
+ for (int n = 0; n < aggstate->shared_info->num_workers; n++)
+ {
+ AggregateInstrumentation *sinstrument;
+ uint64 hash_disk_used;
+ int hash_batches_used;
+
+ sinstrument = &aggstate->shared_info->sinstrument[n];
+ hash_disk_used = sinstrument->hash_disk_used;
+ hash_batches_used = sinstrument->hash_batches_used;
+ memPeakKb = (sinstrument->hash_mem_peak + 1023) / 1024;
+
+ if (es->workers_state)
+ ExplainOpenWorker(n, es);
+
+ if (es->format == EXPLAIN_FORMAT_TEXT)
+ {
+ ExplainIndentText(es);
+
+ appendStringInfo(es->str, "Peak Memory Usage: " INT64_FORMAT " kB",
+ memPeakKb);
+
+ if (hash_batches_used > 0)
+ appendStringInfo(es->str, " Disk Usage: " UINT64_FORMAT " kB HashAgg Batches: %d",
+ hash_disk_used, hash_batches_used);
+ appendStringInfoChar(es->str, '\n');
+ }
+ else
+ {
+ ExplainPropertyInteger("Peak Memory Usage", "kB", memPeakKb,
+ es);
+ if (hash_batches_used > 0)
+ {
+ ExplainPropertyInteger("Disk Usage", "kB", hash_disk_used,
+ es);
+ ExplainPropertyInteger("HashAgg Batches", NULL,
+ hash_batches_used, es);
+ }
+ }
+
+ if (es->workers_state)
+ ExplainCloseWorker(n, es);
+ }
}
}