From a309a9ae632cf3c8f6ff2fe96ca33400d7cea122 Mon Sep 17 00:00:00 2001 From: Ayush Tiwari Date: Sat, 17 Oct 2026 11:00:26 +0000 Subject: [PATCH v1] Accumulate HashAggregate parallel worker stats across rescans ExecEndAgg() overwrites the shared instrumentation for a worker slot. When a Gather or Gather Merge is rescanned, replacement workers reuse those slots, so EXPLAIN ANALYZE reports HashAggregate memory usage, disk usage and batch counts only for the last execution. Keep memory and disk usage maxima across executions. Accumulate the additional spill batches, counting the initial in-memory batch only once, to match how a non-parallel HashAggregate's counters behave across rescans. This is an EXPLAIN reporting bug dating back to 9bdb300dedf; query results are unaffected. --- src/backend/executor/nodeAgg.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 29037cf3122..fa738e2e785 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -4405,9 +4405,14 @@ ExecEndAgg(AggState *node) Assert(ParallelWorkerNumber < node->shared_info->num_workers); si = &node->shared_info->sinstrument[ParallelWorkerNumber]; - si->hash_batches_used = node->hash_batches_used; - si->hash_disk_used = node->hash_disk_used; - si->hash_mem_peak = node->hash_mem_peak; + + /* Workers restart on rescan; count the initial batch only once. */ + if (si->hash_batches_used == 0) + si->hash_batches_used = node->hash_batches_used; + else + si->hash_batches_used += node->hash_batches_used - 1; + si->hash_disk_used = Max(si->hash_disk_used, node->hash_disk_used); + si->hash_mem_peak = Max(si->hash_mem_peak, node->hash_mem_peak); } /* Make sure we have closed any open tuplesorts */ -- 2.43.0