From f4b3ea9a022fda08c448286ecb2628d952841a93 Mon Sep 17 00:00:00 2001 From: TatsuyaKawata Date: Mon, 12 Oct 2026 14:24:05 +0900 Subject: [PATCH v1] Accumulate Memoize parallel worker stats across rescans When a Gather or Gather Merge node is rescanned, it starts a new set of workers, which write their Memoize stats into the same shared memory slots as the previous ones. ExecEndMemoize() used memcpy() for this, so EXPLAIN ANALYZE showed only the stats from the last execution. Accumulate them instead, as is already done for Parallel Bitmap Heap Scan (5a1e6df3b84). --- src/backend/executor/nodeMemoize.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/backend/executor/nodeMemoize.c b/src/backend/executor/nodeMemoize.c index a51dab1803f..70fee823b53 100644 --- a/src/backend/executor/nodeMemoize.c +++ b/src/backend/executor/nodeMemoize.c @@ -1162,7 +1162,19 @@ ExecEndMemoize(MemoizeState *node) Assert(ParallelWorkerNumber < node->shared_info->num_workers); si = &node->shared_info->sinstrument[ParallelWorkerNumber]; - memcpy(si, &node->stats, sizeof(MemoizeInstrumentation)); + + /* + * Here we accumulate the stats rather than performing memcpy on + * node->stats into si. When a Gather/GatherMerge node finishes it + * will perform planner shutdown on the workers. On rescan it will + * spin up new workers which will have a new MemoizeState and zeroed + * stats. + */ + si->cache_hits += node->stats.cache_hits; + si->cache_misses += node->stats.cache_misses; + si->cache_evictions += node->stats.cache_evictions; + si->cache_overflows += node->stats.cache_overflows; + si->mem_peak = Max(si->mem_peak, node->stats.mem_peak); } /* Remove the cache context */ -- 2.34.1