Hi,
On Fri, 17 Jul 2026 at 19:38, Álvaro Herrera <[email protected]> wrote:
> Hello,
>
> On 2026-Jul-17, Ayush Tiwari wrote:
> > I tried the "other way": keep the immediate parent OID on the relcache
> > entry (a lazily-filled rd_partparent), then use the existing walker above
> > that. This avoids repeatedly scanning the leaf link and eliminates the
> > pg_inherits scan entirely for the common one-level hierarchy. Patch
> > attached (fairly small).
>
> Hmm. Why not cache the entire list of ancestors instead of just the
> immediate one? You could have a union that's either a single
> OID (for the most common case where there's only one ancestor), or a
> pointer to an array of an arbitrary number of ancestors. With such a
> system, you only have to scan pg_inherits for a relation once per
> invalidation, regardless of the number of ancestors.
>
> (Looking at pahole's output for RelationData it's obvious that nobody
> cares too much about how much memory that struct takes.)
>
The union is fine, but I don't think a full list cached on the index has
a valid invalidation. AFAICT it depends on the *ancestors'* links, and
re-parenting an intermediate index doesn't invalidate the leaf:
pg_inherits changes send no relcache inval (only
pg_class/pg_attribute/pg_index/pg_constraint do), and IndexSetParentIndex
flips only the re-parented index's own pg_class row.
-- 3-level r > m > l; warm l's index cache
INSERT INTO r VALUES (1) ON CONFLICT (i) DO NOTHING;
NOTICE: FILL l_pkey ancestors=[m_pkey r_pkey]
ALTER TABLE r DETACH PARTITION m;
ALTER TABLE r2 ATTACH PARTITION m ...; -- m_pkey now under r2_pkey
INSERT INTO r2 VALUES (2) ON CONFLICT (i) DO NOTHING;
NOTICE: HIT l_pkey cached=[m_pkey r_pkey] live=[m_pkey r2_pkey] <-STALE
l_pkey is never invalidated, so the cached list keeps r_pkey and
ExecInitPartitionInfo() would pick the wrong arbiter. The
immediate-parent cache dodges this: it stores only the leaf's own parent
(invalidated when it changes) and walks the rest live.
To make a full list safe we'd need a new invalidation path that, on any
index re-parent, invalidates the whole descendant-index subtree rather
than just the re-parented index, and it only helps 3+ level
hierarchies. Should I explore that?
Regards,
Ayush