Use binary search instead of brute-force scan in findNamespace().
authorTom Lane
Fri, 25 May 2012 18:35:37 +0000 (14:35 -0400)
committerTom Lane
Fri, 25 May 2012 18:35:37 +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 9ec180decad1bce2f08024c28da3457c2c4ebfd1..42d3645a6d4f1270856036f497965f41adf31eac 100644 (file)
@@ -48,16 +48,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,
@@ -81,7 +84,6 @@ getSchemaData(Archive *fout, int *numTablesPtr)
    ExtensionInfo *extinfo;
    InhInfo    *inhinfo;
    CollInfo   *collinfo;
-   int         numNamespaces;
    int         numExtensions;
    int         numAggregates;
    int         numInherits;
@@ -101,7 +103,8 @@ getSchemaData(Archive *fout, int *numTablesPtr)
 
    if (g_verbose)
        write_msg(NULL, "reading schemas\n");
-   getNamespaces(fout, &numNamespaces);
+   nspinfo = getNamespaces(fout, &numNamespaces);
+   nspinfoindex = buildIndexArray(nspinfo, numNamespaces, sizeof(NamespaceInfo));
 
    /*
     * getTables should be done as soon as possible, so as to minimize the
@@ -732,6 +735,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 6e13b7462892074dba3ee8d20bd461c51bbada73..46ab6ee2bbceea26aa2ed07cc1130f074852a70f 100644 (file)
@@ -129,10 +129,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;
@@ -2595,8 +2591,7 @@ getNamespaces(Archive *fout, int *numNamespaces)
 
        selectDumpableNamespace(&nsinfo[1]);
 
-       g_namespaces = nsinfo;
-       g_numNamespaces = *numNamespaces = 2;
+       *numNamespaces = 2;
 
        return nsinfo;
    }
@@ -2648,8 +2643,7 @@ getNamespaces(Archive *fout, int *numNamespaces)
    PQclear(res);
    destroyPQExpBuffer(query);
 
-   g_namespaces = nsinfo;
-   g_numNamespaces = *numNamespaces = ntups;
+   *numNamespaces = ntups;
 
    return nsinfo;
 }
@@ -2660,35 +2654,34 @@ getNamespaces(Archive *fout, 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(Archive *fout, Oid nsoid, Oid objoid)
 {
-   int         i;
+   NamespaceInfo *nsinfo;
 
    if (fout->remoteVersion >= 70300)
    {
-       for (i = 0; i < g_numNamespaces; i++)
-       {
-           NamespaceInfo *nsinfo = &g_namespaces[i];
-
-           if (nsoid == nsinfo->dobj.catId.oid)
-               return nsinfo;
-       }
-       exit_horribly(NULL, "schema with OID %u does not exist\n", nsoid);
+       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)
+       exit_horribly(NULL, "schema with OID %u does not exist\n", nsoid);
+
+   return nsinfo;
 }
 
 /*
index 5d6125c42598b593011df0ecb77e26d89e5ec907..f26d8d3ab66e3d4e894f96cdf0f33aa739050e7e 100644 (file)
@@ -511,6 +511,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);