Avoid some overhead with open and close of catalog indexes
authorMichael Paquier <michael@paquier.xyz>
Wed, 16 Nov 2022 01:49:05 +0000 (10:49 +0900)
committerMichael Paquier <michael@paquier.xyz>
Wed, 16 Nov 2022 01:49:05 +0000 (10:49 +0900)
This commit improves two code paths to open and close indexes a
minimum amount of times when doing a series of catalog updates or
inserts.  CatalogTupleInsert() is costly when using it for multiple
inserts or updates compared to CatalogTupleInsertWithInfo(), as it would
need to open and close the indexes of the catalog worked each time an
operation is done.

This commit updates the following places:
- REINDEX CONCURRENTLY when copying statistics from one index relation
to the other.  Multi-INSERTs are avoided here, as this would begin to
show benefits only for indexes with multiple expressions, for example,
which may not be the most common pattern.  This change is noticeable in
profiles with indexes having many expressions, for example, and it would
improve any callers of CopyStatistics().
- Update of statistics on ANALYZE, that mixes inserts and updates.
In each case, the catalog indexes are opened only if at least one
insertion and/or update is required, to minimize the cost of the
operation.  Like the previous coding, no indexes are opened as long as
at least one insert or update of pg_statistic has happened.

Author: Ranier Vilela
Reviewed-by: Kyotaro Horiguchi, Michael Paquier
Discussion: https://postgr.es/m/CAEudQAqh0F9y6Di_Wc8xW4zkWm_5SDd-nRfVsCn=h0Nm1C_mrg@mail.gmail.com

src/backend/catalog/heap.c
src/backend/commands/analyze.c

index 5b49cc5a098968a6c058eabd436f5da705bf555e..bdd413f01b057875a391f9f0a46049c5bb307e7b 100644 (file)
@@ -2856,6 +2856,7 @@ CopyStatistics(Oid fromrelid, Oid torelid)
    SysScanDesc scan;
    ScanKeyData key[1];
    Relation    statrel;
+   CatalogIndexState indstate = NULL;
 
    statrel = table_open(StatisticRelationId, RowExclusiveLock);
 
@@ -2878,13 +2879,20 @@ CopyStatistics(Oid fromrelid, Oid torelid)
 
        /* update the copy of the tuple and insert it */
        statform->starelid = torelid;
-       CatalogTupleInsert(statrel, tup);
+
+       /* fetch index information when we know we need it */
+       if (indstate == NULL)
+           indstate = CatalogOpenIndexes(statrel);
+
+       CatalogTupleInsertWithInfo(statrel, tup, indstate);
 
        heap_freetuple(tup);
    }
 
    systable_endscan(scan);
 
+   if (indstate != NULL)
+       CatalogCloseIndexes(indstate);
    table_close(statrel, RowExclusiveLock);
 }
 
index ff1354812bdd4e237b2cc3be026427f349be4002..bf0ec8b37442be40919b982d44b40abfb501940e 100644 (file)
@@ -1624,6 +1624,7 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
 {
    Relation    sd;
    int         attno;
+   CatalogIndexState indstate = NULL;
 
    if (natts <= 0)
        return;                 /* nothing to do */
@@ -1725,6 +1726,10 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
                                 Int16GetDatum(stats->attr->attnum),
                                 BoolGetDatum(inh));
 
+       /* Open index information when we know we need it */
+       if (indstate == NULL)
+           indstate = CatalogOpenIndexes(sd);
+
        if (HeapTupleIsValid(oldtup))
        {
            /* Yes, replace it */
@@ -1734,18 +1739,20 @@ update_attstats(Oid relid, bool inh, int natts, VacAttrStats **vacattrstats)
                                     nulls,
                                     replaces);
            ReleaseSysCache(oldtup);
-           CatalogTupleUpdate(sd, &stup->t_self, stup);
+           CatalogTupleUpdateWithInfo(sd, &stup->t_self, stup, indstate);
        }
        else
        {
            /* No, insert new tuple */
            stup = heap_form_tuple(RelationGetDescr(sd), values, nulls);
-           CatalogTupleInsert(sd, stup);
+           CatalogTupleInsertWithInfo(sd, stup, indstate);
        }
 
        heap_freetuple(stup);
    }
 
+   if (indstate != NULL)
+       CatalogCloseIndexes(indstate);
    table_close(sd, RowExclusiveLock);
 }