Use binary search instead of brute-force scan in findNamespace().
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 25 May 2012 18:35:41 +0000 (14:35 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 25 May 2012 18:35:41 +0000 (14:35 -0400)
The previous coding presented a significant bottleneck when dumping
databases containing many thousands of schemas, since the total time
spent searching would increase roughly as O(N^2) in the number of objects.
Noted by Jeff Janes, though I rewrote his proposed patch to use the
existing findObjectByOid infrastructure.

Since this is a longstanding performance bug, backpatch to all supported
versions.

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

index d52566d64e4a7eb279079bdaed7604ebcc8c36a6..7415f0d00fb09fd2f4657f29dbe9d1bd1b74e795 100644 (file)
@@ -50,16 +50,19 @@ static TableInfo *tblinfo;
 static TypeInfo *typinfo;
 static FuncInfo *funinfo;
 static OprInfo *oprinfo;
+static NamespaceInfo *nspinfo;
 static int     numTables;
 static int     numTypes;
 static int     numFuncs;
 static int     numOperators;
 static int     numCollations;
+static int     numNamespaces;
 static DumpableObject **tblinfoindex;
 static DumpableObject **typinfoindex;
 static DumpableObject **funinfoindex;
 static DumpableObject **oprinfoindex;
 static DumpableObject **collinfoindex;
+static DumpableObject **nspinfoindex;
 
 
 static void flagInhTables(TableInfo *tbinfo, int numTables,
@@ -83,7 +86,6 @@ getSchemaData(int *numTablesPtr)
        ExtensionInfo *extinfo;
        InhInfo    *inhinfo;
        CollInfo   *collinfo;
-       int                     numNamespaces;
        int                     numExtensions;
        int                     numAggregates;
        int                     numInherits;
@@ -103,7 +105,8 @@ getSchemaData(int *numTablesPtr)
 
        if (g_verbose)
                write_msg(NULL, "reading schemas\n");
-       getNamespaces(&numNamespaces);
+       nspinfo = getNamespaces(&numNamespaces);
+       nspinfoindex = buildIndexArray(nspinfo, numNamespaces, sizeof(NamespaceInfo));
 
        /*
         * getTables should be done as soon as possible, so as to minimize the
@@ -734,6 +737,17 @@ findCollationByOid(Oid oid)
        return (CollInfo *) findObjectByOid(oid, collinfoindex, numCollations);
 }
 
+/*
+ * findNamespaceByOid
+ *       finds the entry (in nspinfo) of the namespace with the given oid
+ *       returns NULL if not found
+ */
+NamespaceInfo *
+findNamespaceByOid(Oid oid)
+{
+       return (NamespaceInfo *) findObjectByOid(oid, nspinfoindex, numNamespaces);
+}
+
 
 /*
  * findParentsByOid
index a4c6d420ec64b7007f38bd08cd94c47799a5ff3a..665f758db04b4add7763cf79f1c8f2ecd9dd7cca 100644 (file)
@@ -126,10 +126,6 @@ char               g_comment_end[10];
 
 static const CatalogId nilCatalogId = {0, 0};
 
-/* these are to avoid passing around info for findNamespace() */
-static NamespaceInfo *g_namespaces;
-static int     g_numNamespaces;
-
 /* flags for various command-line long options */
 static int     binary_upgrade = 0;
 static int     disable_dollar_quoting = 0;
@@ -2619,8 +2615,7 @@ getNamespaces(int *numNamespaces)
 
                selectDumpableNamespace(&nsinfo[1]);
 
-               g_namespaces = nsinfo;
-               g_numNamespaces = *numNamespaces = 2;
+               *numNamespaces = 2;
 
                return nsinfo;
        }
@@ -2673,8 +2668,7 @@ getNamespaces(int *numNamespaces)
        PQclear(res);
        destroyPQExpBuffer(query);
 
-       g_namespaces = nsinfo;
-       g_numNamespaces = *numNamespaces = ntups;
+       *numNamespaces = ntups;
 
        return nsinfo;
 }
@@ -2685,36 +2679,37 @@ getNamespaces(int *numNamespaces)
  *             getNamespaces
  *
  * NB: for pre-7.3 source database, we use object OID to guess whether it's
- * a system object or not.     In 7.3 and later there is no guessing.
+ * a system object or not.     In 7.3 and later there is no guessing, and we
+ * don't use objoid at all.
  */
 static NamespaceInfo *
 findNamespace(Oid nsoid, Oid objoid)
 {
-       int                     i;
+       NamespaceInfo *nsinfo;
 
        if (g_fout->remoteVersion >= 70300)
        {
-               for (i = 0; i < g_numNamespaces; i++)
-               {
-                       NamespaceInfo *nsinfo = &g_namespaces[i];
-
-                       if (nsoid == nsinfo->dobj.catId.oid)
-                               return nsinfo;
-               }
-               write_msg(NULL, "schema with OID %u does not exist\n", nsoid);
-               exit_nicely();
+               nsinfo = findNamespaceByOid(nsoid);
        }
        else
        {
-               /* This code depends on the layout set up by getNamespaces. */
+               /* This code depends on the dummy objects set up by getNamespaces. */
+               Oid             i;
+
                if (objoid > g_last_builtin_oid)
                        i = 0;                          /* user object */
                else
                        i = 1;                          /* system object */
-               return &g_namespaces[i];
+               nsinfo = findNamespaceByOid(i);
        }
 
-       return NULL;                            /* keep compiler quiet */
+       if (nsinfo == NULL)
+       {
+               write_msg(NULL, "schema with OID %u does not exist\n", nsoid);
+               exit_nicely();
+       }
+
+       return nsinfo;
 }
 
 /*
index 37b19d2f12e55f539c186bc7f0b7ab4f5af52e64..21d42f8ea5365754e87f64a57cab00f36c9cb2d9 100644 (file)
@@ -506,6 +506,7 @@ extern TypeInfo *findTypeByOid(Oid oid);
 extern FuncInfo *findFuncByOid(Oid oid);
 extern OprInfo *findOprByOid(Oid oid);
 extern CollInfo *findCollationByOid(Oid oid);
+extern NamespaceInfo *findNamespaceByOid(Oid oid);
 
 extern void simple_oid_list_append(SimpleOidList *list, Oid val);
 extern void simple_string_list_append(SimpleStringList *list, const char *val);