[PATCH] Planner support function for generate_subscripts()

From: shihao zhong <zhong950419(at)gmail(dot)com>
To: pgsql-hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: [PATCH] Planner support function for generate_subscripts()
Date: 2026-08-31 02:04:00
Message-ID: CAGRkXqQ6BLCkEBBC2OC_bvEaUPTg+z+2-euiJKKvAxgA7o1EAA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi hackers,
generate_subscripts() has no planner support function, so its row
estimate is always the prorows value of 1000, no matter what the
arguments are. unnest() has been estimating its row count from the
array argument since v12. The attached 0001 does the same for
generate_subscripts().

One difference from unnest() is that generate_subscripts() returns
one row per subscript of the requested dimension, not one row per
element. An exact answer is therefore only possible when the array
is a plan-time constant.

The support function handles three cases:

1. If any argument is a constant NULL, it reports zero rows, since the
function is strict.
2. If both the array and the dimension number are
constants, it reports the exact length of that dimension.
3. If only the dimension number is known and it is 1, it uses
estimate_array_length().

That works because for one-dimensional arrays, the element count
equals the length of dimension 1. In all other cases it declines and
prorows applies as before.

This can change plans for the better. Joining five subscripts
against an indexed table:
Hash Join (cost=637.00..649.63 rows=1000 width=45)
Hash Cond: (s.s = items.id)
-> Function Scan on generate_subscripts s (rows=1000) (actual rows=5)
-> Hash
-> Seq Scan on items (rows=20000)
becomes
Nested Loop (cost=0.29..41.58 rows=5 width=45)
-> Function Scan on generate_subscripts s (rows=5) (actual rows=5)
-> Index Scan using items_pkey on items

A note on the statistics path. estimate_array_length() uses the
DECHIST average, which counts distinct elements, so arrays with many
duplicate or NULL elements get underestimated. unnest() behaves the
same way. Fixing that centrally looks like separate work. The new
regression tests use arrays of distinct elements to keep the expected
output deterministic.

0002 lowers prorows from 1000 to 100. After 0001, prorows is only
reached when the dimension number is unknown at plan time, or when a
higher dimension of a non-constant array is requested. 100 matches
what unnest() uses. I kept it as a separate patch so it can be taken
or dropped on its own.

CatVersion bump is required.

Thanks,
Shihao

Attachment Content-Type Size
v1-0002-Lower-generate_subscripts-s-prorows-estimate-to-m.patch application/octet-stream 4.2 KB
v1-0001-Add-a-planner-support-function-for-generate_subsc.patch application/octet-stream 20.1 KB

Browse pgsql-hackers by date

  From Date Subject
Next Message shihao zhong 2026-08-31 02:21:21 [PATCH] Add row estimate tests for unnest() and integer generate_series()
Previous Message Tender Wang 2026-08-31 01:55:24 Re: remove_useless_joins vs. bug #19560