| From: | Tatsuya Kawata <kawatatatsuya0913(at)gmail(dot)com> |
|---|---|
| To: | PostgreSQL-development <pgsql-hackers(at)postgresql(dot)org> |
| Subject: | [PATCH] Add memory/disk usage for Function Scan nodes in EXPLAIN |
| Date: | 2026-08-16 06:14:05 |
| Message-ID: | CAHza6qdpZTTjGJdzUmBkWbDPGB=gsz-vZWm5dO-oim_NrjAXCQ@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi,
1eff8279d4, 95d6e9af07 and 40708acd65 added memory/disk usage for
Materialize, WindowAgg, CTE Scan, Table Function Scan and Recursive
Union in EXPLAIN ANALYZE. [1]
So I wanted to add memory/disk usage for Function Scan.
## The patch
It follows the shape of the existing five nodes, so there are only two
things worth mentioning.
1. Handling of multiple tuplestores
A FunctionScan uses one tuplestore per function, so there can be more
than one when ROWS FROM is used. I used the same rule as Recursive
Union: the storage type of whichever one consumed the most
memory/disk, and the sum of the sizes of them all.
2. Moving FunctionScanPerFuncState to execnodes.h
Its definition lives in nodeFunctionscan.c and execnodes.h only has a
forward declaration, so explain.c cannot reach funcstates[i].tstore.
The state structs of the other five nodes are all in execnodes.h, so
I moved this one there too.
## Behavior
Measured with work_mem = 64kB. On its own, 1000 rows gives
"Memory 56kB" and 500000 rows gives "Disk 6836kB".
-- two identical functions: exactly twice the single-function figure
SELECT count(*) FROM ROWS FROM (generate_series(1,500000),
generate_series(1,500000)) g;
Storage: Disk Maximum Storage: 13672kB
-- a small one and a large one: type from the larger, size is the sum
SELECT count(*) FROM ROWS FROM (generate_series(1,10),
generate_series(1,500000)) g;
Storage: Disk Maximum Storage: 6853kB
## What is reported when loops > 1
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 could not find a settled policy for how this kind of per-node resource
statistic should be aggregated when loops > 1. So this patch follows
Sort. If the consensus is that the maximum across all loops should be
reported instead, that would be a separate change spanning Sort,
Incremental Sort, Material, Table Function Scan and Function Scan, and
I would be happy to work on it separately.
make check passes all 245 tests.
Patch attached.
Regards,
Tatsuya Kawata
[1] Discussion for 40708acd65:
https://postgr.es/m/20240918.211246.1127161704188186085.ishii%40postgresql.org
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0001-Add-memory-disk-usage-for-Function-Scan-nodes-in-.patch | application/octet-stream | 13.3 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Alexandre Felipe | 2026-08-16 06:14:48 | Re: Restructured Shared Buffer Hash Table |
| Previous Message | Bharath Rupireddy | 2026-08-16 05:35:00 | Re: Introduce XID age based replication slot invalidation |