Re: [PATCH] Add memory/disk usage for Function Scan nodes in EXPLAIN

From: David Rowley <dgrowleyml(at)gmail(dot)com>
To: Tatsuya Kawata <kawatatatsuya0913(at)gmail(dot)com>
Cc: PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: [PATCH] Add memory/disk usage for Function Scan nodes in EXPLAIN
Date: 2026-09-30 01:46:05
Message-ID: CAApHDvoFPyT10sRDY+bH1MOwHwWNnBQKR7xgEePDke15-EkMkQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Sun, 16 Aug 2026 at 18:14, Tatsuya Kawata
<kawatatatsuya0913(at)gmail(dot)com> wrote:
> The Storage line follows the same policy as the Sort Method line of
> Sort, that is, it reports the peak recorded by whichever object is still
> around at EXPLAIN time. The statistics live inside the Tuplestorestate
> (or Tuplesortstate) and are lost along with it when rescan calls end().
> ExecReScanFunctionScan() has the same shape as
> ExecReScanTableFuncScan(), and on master both Sort and Table Function
> Scan already change what they report if you reorder the rows.
> When loops is 1 the value is of course exact.

I understand that's what a few other nodes do, but I don't think
that's a great example to follow, especially given that the EXPLAIN
text claims the value is "Maximum Storage".

Looking at the output of the following, I've only swapped the VALUES
order. The memory reported by the patch is quite different in each
case.

explain analyze select a,g.s from (values(10000000),(1)) a(a), lateral
generate_series(1,a.a) g(s);

-> Function Scan on generate_series g (cost=0.00..10.00 rows=1000
width=4) (actual time=852.914..1477.110 rows=5000000.50 loops=2)
Storage: Memory Maximum Storage: 17kB

explain analyze select a,g.s from (values(1),(10000000)) a(a), lateral
generate_series(1,a.a) g(s);

-> Function Scan on generate_series g (cost=0.00..10.00 rows=1000
width=4) (actual time=838.233..1448.676 rows=5000000.50 loops=2)
Storage: Disk Maximum Storage: 136719kB

Can you prepare an initial patch that swaps tuplestore_end() for
tuplestore_clear() in the relevant locations (similar to what
908a96861 did). This can go in separately on the justification that
it's an optimisation to avoid the reallocation of fields that are
pfree'd in tuplestore_end().

I'll look at doing this for nodeMaterial.c. It might be somewhat
harder to get a plan with a parameterised Material node, however, but
it should be possible.

David

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Rustam ALLAKOV 2026-09-30 01:50:39 Re: Improve cube GiST page splits
Previous Message Corey Huinker 2026-09-30 01:31:27 Re: Credits For v19