Cache typarray for fast lookups in binary upgrade mode
authorDaniel Gustafsson <dgustafsson@postgresql.org>
Mon, 2 Sep 2024 08:17:46 +0000 (10:17 +0200)
committerDaniel Gustafsson <dgustafsson@postgresql.org>
Mon, 2 Sep 2024 08:17:46 +0000 (10:17 +0200)
When upgrading a large schema it adds significant overhead to perform
individual catalog lookups per relation in order to retrieve Oid for
preserving Oid calls. This instead adds the typarray to the TypeInfo
cache which then allows for fast lookups using the existing API. A
35% reduction of pg_dump runtime in binary upgrade mode was observed
with this change.

Reviewed-by: Nathan Bossart <nathandbossart@gmail.com>
Discussion: https://postgr.es/m/8F1F1E1D-D17B-4B33-B014-EDBCD15F3F0B@yesql.se

src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h

index f7720ad53b749d9b218da8363a59f427ba97f5fd..dacb033e989416c99135eab01f606c5946e7209d 100644 (file)
@@ -5412,23 +5412,15 @@ binary_upgrade_set_type_oids_by_type_oid(Archive *fout,
        Oid                     pg_type_array_oid;
        Oid                     pg_type_multirange_oid;
        Oid                     pg_type_multirange_array_oid;
+       TypeInfo   *tinfo;
 
        appendPQExpBufferStr(upgrade_buffer, "\n-- For binary upgrade, must preserve pg_type oid\n");
        appendPQExpBuffer(upgrade_buffer,
                                          "SELECT pg_catalog.binary_upgrade_set_next_pg_type_oid('%u'::pg_catalog.oid);\n\n",
                                          pg_type_oid);
 
-       appendPQExpBuffer(upgrade_query,
-                                         "SELECT typarray "
-                                         "FROM pg_catalog.pg_type "
-                                         "WHERE oid = '%u'::pg_catalog.oid;",
-                                         pg_type_oid);
-
-       res = ExecuteSqlQueryForSingleRow(fout, upgrade_query->data);
-
-       pg_type_array_oid = atooid(PQgetvalue(res, 0, PQfnumber(res, "typarray")));
-
-       PQclear(res);
+       tinfo = findTypeByOid(pg_type_oid);
+       pg_type_array_oid = tinfo->typarray;
 
        if (!OidIsValid(pg_type_array_oid) && force_array_type)
                pg_type_array_oid = get_next_possible_free_pg_type_oid(fout, upgrade_query);
@@ -5910,6 +5902,7 @@ getTypes(Archive *fout)
        int                     i_typtype;
        int                     i_typisdefined;
        int                     i_isarray;
+       int                     i_typarray;
 
        /*
         * we include even the built-in types because those may be used as array
@@ -5930,7 +5923,7 @@ getTypes(Archive *fout)
                                                 "typnamespace, typacl, "
                                                 "acldefault('T', typowner) AS acldefault, "
                                                 "typowner, "
-                                                "typelem, typrelid, "
+                                                "typelem, typrelid, typarray, "
                                                 "CASE WHEN typrelid = 0 THEN ' '::\"char\" "
                                                 "ELSE (SELECT relkind FROM pg_class WHERE oid = typrelid) END AS typrelkind, "
                                                 "typtype, typisdefined, "
@@ -5957,6 +5950,7 @@ getTypes(Archive *fout)
        i_typtype = PQfnumber(res, "typtype");
        i_typisdefined = PQfnumber(res, "typisdefined");
        i_isarray = PQfnumber(res, "isarray");
+       i_typarray = PQfnumber(res, "typarray");
 
        for (i = 0; i < ntups; i++)
        {
@@ -5989,6 +5983,8 @@ getTypes(Archive *fout)
                else
                        tyinfo[i].isArray = false;
 
+               tyinfo[i].typarray = atooid(PQgetvalue(res, i, i_typarray));
+
                if (tyinfo[i].typtype == TYPTYPE_MULTIRANGE)
                        tyinfo[i].isMultirange = true;
                else
index 4b2e5870a9cef04b594e0cd03e6fbca6d71432bb..0b7d21b2e9b559d2cfee4a444fc9f693a9f7af96 100644 (file)
@@ -200,6 +200,7 @@ typedef struct _typeInfo
        const char *rolname;
        Oid                     typelem;
        Oid                     typrelid;
+       Oid                     typarray;
        char            typrelkind;             /* 'r', 'v', 'c', etc */
        char            typtype;                /* 'b', 'c', etc */
        bool            isArray;                /* true if auto-generated array type */