Re: Something is rotten in publication drop

From: Peter Eisentraut <peter(dot)eisentraut(at)2ndquadrant(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: Something is rotten in publication drop
Date: 2017-06-16 03:38:08
Message-ID: 34140e2f-a18e-9733-e767-3777adb55a34@2ndquadrant.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 6/15/17 12:23, Tom Lane wrote:
> It strikes me that you could rewrite psql's query to just do its own
> catalog search and not bother with the function at all. It would have
> to know a bit more about the catalog structure than it does now, but not
> that much:
>
> select pub.pubname from pg_catalog.pg_publication pub
> where puballtables or
> exists(select 1 from pg_catalog.pg_publication_rel r
> where r.prpubid = pub.oid and r.prrelid = '%s');

We used to do something like that, but then people complained that that
was not absolutely accurate, because it did not exclude catalog tables
and related things properly. See commit
2d460179baa8744e9e2a183a5121306596c53fba. To do this properly, you need
to filter pg_class using is_publishable_class() (hitherto internal C
function).

The way this was originally written was for use by subscriptioncmds.c
fetch_table_list(), which generally only deals with a small number of
publications as the search key and wants to find all the relations. The
psql use case is exactly the opposite: We start with a relation and want
to find all the publications. The third use case is that we document
the view pg_publication_tables for general use, so depending on which
search key you start with, you might get terrible performance if you
have a lot of tables.

An academically nice way to write a general query for this would be:

CREATE VIEW pg_publication_tables AS
SELECT
p.pubname AS pubname,
n.nspname AS schemaname,
c.relname AS tablename,
c.oid AS relid
FROM pg_publication p
JOIN pg_publication_rel pr ON p.oid = pr.prpubid
JOIN pg_class c ON pr.prrelid = c.oid
JOIN pg_namespace n ON c.relnamespace = n.oid
UNION
SELECT
p.pubname AS pubname,
n.nspname AS schemaname,
c.relname AS tablename,
c.oid AS relid
FROM pg_publication p
JOIN pg_class c ON p.puballtables AND
pg_is_relation_publishable(c.oid)
JOIN pg_namespace n ON c.relnamespace = n.oid;

But looking at the plans this generates, it will do a sequential scan of
pg_class even if you look for a publication that is not puballtables,
which would suck for the subscriptioncmds.c use case.

We could use the above definition for the documented view and the psql
use case.

We could then create second view that uses the existing definition

CREATE VIEW pg_publication_tables AS
SELECT
P.pubname AS pubname,
N.nspname AS schemaname,
C.relname AS tablename
FROM pg_publication P, pg_class C
JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE C.oid IN (SELECT relid FROM pg_get_publication_tables(P.pubname));

for use in subscriptioncmds.c. Or don't use a view for that. But the
view is useful because we should preserve this interface across versions.

Or we throw away all the views and use custom code everywhere.

Patch for experimentation attached.

Any ideas?

--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

Attachment Content-Type Size
0001-WIP-Tweak-publication-fetching-in-psql.patch text/plain 4.0 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Peter Eisentraut 2017-06-16 03:40:52 Re: Get stuck when dropping a subscription during synchronizing table
Previous Message Michael Paquier 2017-06-16 02:34:34 Re: PATCH: Don't downcase filepath/filename while loading libraries