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?