Permalink
Browse files

Fix O(N^2) behavior in pg_dump for large numbers of owned sequences.

The loop that matched owned sequences to their owning tables required time
proportional to number of owned sequences times number of tables; although
this work was only expended in selective-dump situations, which is probably
why the issue wasn't recognized long since.  Refactor slightly so that we
can perform this work after the index array for findTableByOid has been
set up, reducing the time to O(M log N).

Per gripe from Mike Roest.  Since this is a longstanding performance bug,
backpatch to all supported versions.
  • Loading branch information...
tglsfdc committed Mar 31, 2012
1 parent c252a17 commit 0d8117abefdae69dbec7465adf2c68f5cd0412ac
Showing with 27 additions and 18 deletions.
  1. +3 −0 src/bin/pg_dump/common.c
  2. +23 −18 src/bin/pg_dump/pg_dump.c
  3. +1 −0 src/bin/pg_dump/pg_dump.h
@@ -114,6 +114,9 @@ getSchemaData(Archive *fout, int *numTablesPtr)
tblinfo = getTables(fout, &numTables);
tblinfoindex = buildIndexArray(tblinfo, numTables, sizeof(TableInfo));

/* Do this after we've built tblinfoindex */
getOwnedSeqs(fout, tblinfo, numTables);

if (g_verbose)
write_msg(NULL, "reading extensions\n");
extinfo = getExtensions(fout, &numExtensions);
@@ -4307,38 +4307,43 @@ getTables(Archive *fout, int *numTables)

PQclear(res);

destroyPQExpBuffer(query);

return tblinfo;
}

/*
* getOwnedSeqs
* identify owned sequences and mark them as dumpable if owning table is
*
* We used to do this in getTables(), but it's better to do it after the
* index used by findTableByOid() has been set up.
*/
void
getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables)
{
int i;

/*
* Force sequences that are "owned" by table columns to be dumped whenever
* their owning table is being dumped.
*/
for (i = 0; i < ntups; i++)
for (i = 0; i < numTables; i++)
{
TableInfo *seqinfo = &tblinfo[i];
int j;
TableInfo *owning_tab;

if (!OidIsValid(seqinfo->owning_tab))
continue; /* not an owned sequence */
if (seqinfo->dobj.dump)
continue; /* no need to search */

/* can't use findTableByOid yet, unfortunately */
for (j = 0; j < ntups; j++)
owning_tab = findTableByOid(seqinfo->owning_tab);
if (owning_tab && owning_tab->dobj.dump)
{
if (tblinfo[j].dobj.catId.oid == seqinfo->owning_tab)
{
if (tblinfo[j].dobj.dump)
{
seqinfo->interesting = true;
seqinfo->dobj.dump = true;
}
break;
}
seqinfo->interesting = true;
seqinfo->dobj.dump = true;
}
}

destroyPQExpBuffer(query);

return tblinfo;
}

/*
@@ -538,6 +538,7 @@ extern OpfamilyInfo *getOpfamilies(Archive *fout, int *numOpfamilies);
extern CollInfo *getCollations(Archive *fout, int *numCollations);
extern ConvInfo *getConversions(Archive *fout, int *numConversions);
extern TableInfo *getTables(Archive *fout, int *numTables);
extern void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables);
extern InhInfo *getInherits(Archive *fout, int *numInherits);
extern void getIndexes(Archive *fout, TableInfo tblinfo[], int numTables);
extern void getConstraints(Archive *fout, TableInfo tblinfo[], int numTables);

0 comments on commit 0d8117a

Please sign in to comment.