Re: Partial indexes on system catalogs - Mailing list pgsql-hackers

From Manu
Subject Re: Partial indexes on system catalogs
Date
Msg-id 179095798087.305358.9328662541229277643@gmail.com
Whole thread
In response to Re: Partial indexes on system catalogs  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
Thanks, both, for the quick read -- and to Álvaro, whose suggestion in
the ATTACH-partition thread to look at these catalogs is what started
this.

Andres Freund <andres@anarazel.de> writes:
> Is the gain from that really substantial enough to warrant introducing
> this?  Catcache keeps negative lookup matches [...]

Fair enough; I'll drop the partial-index approach.  As you both say,
with pg_constraint as it stands the catcache already covers most of it,
and a whitelist of allowed predicates is a hack, not partial indexes.

Tom Lane <tgl@sss.pgh.pa.us> writes:
> More generally, the real problem here is that pg_constraint is
> misdesigned and in need of a refactoring.  [...]  in particular maybe
> the breakouts should be designed along some other principle than
> "what's the contype".

I went down that road to see where it leads, and a couple of things came
out that I'd value your read on.

On the split principle: contype isn't a clean key.  conexclop is shared
by EXCLUSION and by PRIMARY KEY/UNIQUE with WITHOUT OVERLAPS; conindid
means different things for a foreign key (an index on the referenced
relation) versus a unique constraint (an index on conrelid); and CHECK
already spans relation and domain constraints.  The cohesive groups look
like capabilities, not types.

More important, the compatibility view in your (c) runs into object
identity.  A constraint's classid in pg_depend is ConstraintRelationId,
and the deletion path does table_open(classid), so classid has to stay a
real, scannable catalog -- it can't be a view; and information_schema
itself compares classid against 'pg_constraint'::regclass.  The
pg_aggregate precedent you cited actually points the other way: pg_proc
keeps the identity and pg_aggregate only extends it, with no pg_proc
view.

So I prototyped that shape: pg_constraint stays the catalog, and a
pg_constraint_fkey breakout holds the foreign-key-only columns, keyed by
the constraint OID, the way pg_aggregate extends pg_proc.  confrelid
lives in the breakout, where every row is a foreign key, so an ordinary
index on it is dense -- no partial predicate and none of the sparse zero
entries you were wary of.

On that prototype the scans you both flagged become index scans.  In
wall time, ATTACH PARTITION on the referenced side -- the
CloneFkReferenced scan from that thread -- grows with the catalog, from
about 1 ms at ten thousand constraints to ~43 ms at a million; against
the breakout it stays flat near 2 ms, and DETACH goes from ~78 ms at a
million down to ~3 ms.  The plan is the clearest evidence; at 200k
constraints the referencing-key lookup on master is

 Seq Scan on pg_constraint (actual time=0.113..31.204 rows=3.00)
   Rows Removed by Filter: 200203
   Buffers: shared hit=12828 read=2562

and against the breakout

 Seq Scan on pg_constraint_fkey (actual time=0.120..0.121 rows=3.00)
   Rows Removed by Filter: 3
   Buffers: shared read=1

which is O(catalog) versus O(1).  The breakout holds only foreign keys,
so the lookup touches one page here; when the foreign keys themselves
are numerous the confrelid index keeps it flat as well.  So the
direction does buy the thing the thread started from.

The open question I can't settle alone is the one your (c) was meant to
solve.  The dense confrelid index needs confrelid to move into the
breakout, but confrelid on pg_constraint is exactly what clients select;
performance and "what clients see" pull against each other on that one
column, and a compat view to hide the move reintroduces the classid
problem above.  Is a loud, pg_aggregate-style compatibility break
acceptable here, or does that tension argue for leaving confrelid on
pg_constraint and just adding the plain index?

Either way the immediate confrelid lookup is covered by the plain
non-unique index proposed separately, independent of this.

This is exploratory -- a prototype to test whether the refactoring
direction holds up, not a patch for commit.  I'm happy to share the
branch if it helps.  Does this match how you were thinking about it?

Thanks,
Manu



pgsql-hackers by date:

Previous
From: Etsuro Fujita
Date:
Subject: Re: postgres_fdw: transaction mode inheritance corner cases
Next
From: Nathan Bossart
Date:
Subject: Re: Teach pg_upgrade to deal with invalid databases