Re: Caching a partition index's parent OID in the relcache? - Mailing list pgsql-hackers

From Ayush Tiwari
Subject Re: Caching a partition index's parent OID in the relcache?
Date
Msg-id CAJTYsWXquWQR2cY9jjfSjG7nFHhTD_GW1hFO6xnQSXBtfNk3tA@mail.gmail.com
Whole thread
In response to Re: Caching a partition index's parent OID in the relcache?  (Álvaro Herrera <alvherre@kurilemu.de>)
List pgsql-hackers
Hi,

On Fri, 17 Jul 2026 at 19:38, Álvaro Herrera <alvherre@kurilemu.de> 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

pgsql-hackers by date:

Previous
From: Andres Freund
Date:
Subject: Re: Heads Up: cirrus-ci is shutting down June 1st
Next
From: 신성준
Date:
Subject: Re: Add wait events for server logging destination writes