mirror of
https://github.com/postgres/postgres.git
synced 2025-05-28 00:03:23 -04:00
Simplify and speed up pg_dump's creation of parent-table links.
Instead of trying to optimize this by skipping creation of the links for tables we don't plan to dump, just create them all in bulk with a single scan over the pg_inherits data. The previous approach was more or less O(N^2) in the number of pg_inherits entries, not to mention being way too complicated. Also, don't create useless TableAttachInfo objects. It's silly to create a TableAttachInfo object that we're not going to dump, when we know perfectly well at creation time that it won't be dumped. Patch by me; thanks to Julien Rouhaud for review. Discussion: https://postgr.es/m/1376149.1675268279@sss.pgh.pa.us
This commit is contained in:
parent
bc8cd50fef
commit
064709f803
@ -83,8 +83,6 @@ static void flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables,
|
|||||||
InhInfo *inhinfo, int numInherits);
|
InhInfo *inhinfo, int numInherits);
|
||||||
static void flagInhIndexes(Archive *fout, TableInfo *tblinfo, int numTables);
|
static void flagInhIndexes(Archive *fout, TableInfo *tblinfo, int numTables);
|
||||||
static void flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables);
|
static void flagInhAttrs(DumpOptions *dopt, TableInfo *tblinfo, int numTables);
|
||||||
static void findParentsByOid(TableInfo *self,
|
|
||||||
InhInfo *inhinfo, int numInherits);
|
|
||||||
static int strInArray(const char *pattern, char **arr, int arr_size);
|
static int strInArray(const char *pattern, char **arr, int arr_size);
|
||||||
static IndxInfo *findIndexByOid(Oid oid);
|
static IndxInfo *findIndexByOid(Oid oid);
|
||||||
|
|
||||||
@ -288,45 +286,70 @@ static void
|
|||||||
flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables,
|
flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables,
|
||||||
InhInfo *inhinfo, int numInherits)
|
InhInfo *inhinfo, int numInherits)
|
||||||
{
|
{
|
||||||
|
TableInfo *child = NULL;
|
||||||
|
TableInfo *parent = NULL;
|
||||||
int i,
|
int i,
|
||||||
j;
|
j;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up links from child tables to their parents.
|
||||||
|
*
|
||||||
|
* We used to attempt to skip this work for tables that are not to be
|
||||||
|
* dumped; but the optimizable cases are rare in practice, and setting up
|
||||||
|
* these links in bulk is cheaper than the old way. (Note in particular
|
||||||
|
* that it's very rare for a child to have more than one parent.)
|
||||||
|
*/
|
||||||
|
for (i = 0; i < numInherits; i++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Skip a hashtable lookup if it's same table as last time. This is
|
||||||
|
* unlikely for the child, but less so for the parent. (Maybe we
|
||||||
|
* should ask the backend for a sorted array to make it more likely?
|
||||||
|
* Not clear the sorting effort would be repaid, though.)
|
||||||
|
*/
|
||||||
|
if (child == NULL ||
|
||||||
|
child->dobj.catId.oid != inhinfo[i].inhrelid)
|
||||||
|
{
|
||||||
|
child = findTableByOid(inhinfo[i].inhrelid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we find no TableInfo, assume the pg_inherits entry is for a
|
||||||
|
* partitioned index, which we don't need to track.
|
||||||
|
*/
|
||||||
|
if (child == NULL)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (parent == NULL ||
|
||||||
|
parent->dobj.catId.oid != inhinfo[i].inhparent)
|
||||||
|
{
|
||||||
|
parent = findTableByOid(inhinfo[i].inhparent);
|
||||||
|
if (parent == NULL)
|
||||||
|
pg_fatal("failed sanity check, parent OID %u of table \"%s\" (OID %u) not found",
|
||||||
|
inhinfo[i].inhparent,
|
||||||
|
child->dobj.name,
|
||||||
|
child->dobj.catId.oid);
|
||||||
|
}
|
||||||
|
/* Add this parent to the child's list of parents. */
|
||||||
|
if (child->numParents > 0)
|
||||||
|
child->parents = pg_realloc_array(child->parents,
|
||||||
|
TableInfo *,
|
||||||
|
child->numParents + 1);
|
||||||
|
else
|
||||||
|
child->parents = pg_malloc_array(TableInfo *, 1);
|
||||||
|
child->parents[child->numParents++] = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now consider all child tables and mark parents interesting as needed.
|
||||||
|
*/
|
||||||
for (i = 0; i < numTables; i++)
|
for (i = 0; i < numTables; i++)
|
||||||
{
|
{
|
||||||
bool find_parents = true;
|
|
||||||
bool mark_parents = true;
|
|
||||||
|
|
||||||
/* Some kinds never have parents */
|
|
||||||
if (tblinfo[i].relkind == RELKIND_SEQUENCE ||
|
|
||||||
tblinfo[i].relkind == RELKIND_VIEW ||
|
|
||||||
tblinfo[i].relkind == RELKIND_MATVIEW)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Normally, we don't bother computing anything for non-target tables.
|
|
||||||
* However, we must find the parents of non-root partitioned tables in
|
|
||||||
* any case, so that we can trace from leaf partitions up to the root
|
|
||||||
* (in case a leaf is to be dumped but its parents are not). We need
|
|
||||||
* not mark such parents interesting for getTableAttrs, though.
|
|
||||||
*/
|
|
||||||
if (!tblinfo[i].dobj.dump)
|
|
||||||
{
|
|
||||||
mark_parents = false;
|
|
||||||
|
|
||||||
if (!(tblinfo[i].relkind == RELKIND_PARTITIONED_TABLE &&
|
|
||||||
tblinfo[i].ispartition))
|
|
||||||
find_parents = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If needed, find all the immediate parent tables. */
|
|
||||||
if (find_parents)
|
|
||||||
findParentsByOid(&tblinfo[i], inhinfo, numInherits);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If needed, mark the parents as interesting for getTableAttrs and
|
* If needed, mark the parents as interesting for getTableAttrs and
|
||||||
* getIndexes.
|
* getIndexes. We only need this for direct parents of dumpable
|
||||||
|
* tables.
|
||||||
*/
|
*/
|
||||||
if (mark_parents)
|
if (tblinfo[i].dobj.dump)
|
||||||
{
|
{
|
||||||
int numParents = tblinfo[i].numParents;
|
int numParents = tblinfo[i].numParents;
|
||||||
TableInfo **parents = tblinfo[i].parents;
|
TableInfo **parents = tblinfo[i].parents;
|
||||||
@ -336,7 +359,8 @@ flagInhTables(Archive *fout, TableInfo *tblinfo, int numTables,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create TableAttachInfo object if needed */
|
/* Create TableAttachInfo object if needed */
|
||||||
if (tblinfo[i].dobj.dump && tblinfo[i].ispartition)
|
if ((tblinfo[i].dobj.dump & DUMP_COMPONENT_DEFINITION) &&
|
||||||
|
tblinfo[i].ispartition)
|
||||||
{
|
{
|
||||||
TableAttachInfo *attachinfo;
|
TableAttachInfo *attachinfo;
|
||||||
|
|
||||||
@ -995,52 +1019,6 @@ findOwningExtension(CatalogId catalogId)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* findParentsByOid
|
|
||||||
* find a table's parents in tblinfo[]
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
findParentsByOid(TableInfo *self,
|
|
||||||
InhInfo *inhinfo, int numInherits)
|
|
||||||
{
|
|
||||||
Oid oid = self->dobj.catId.oid;
|
|
||||||
int i,
|
|
||||||
j;
|
|
||||||
int numParents;
|
|
||||||
|
|
||||||
numParents = 0;
|
|
||||||
for (i = 0; i < numInherits; i++)
|
|
||||||
{
|
|
||||||
if (inhinfo[i].inhrelid == oid)
|
|
||||||
numParents++;
|
|
||||||
}
|
|
||||||
|
|
||||||
self->numParents = numParents;
|
|
||||||
|
|
||||||
if (numParents > 0)
|
|
||||||
{
|
|
||||||
self->parents = pg_malloc_array(TableInfo *, numParents);
|
|
||||||
j = 0;
|
|
||||||
for (i = 0; i < numInherits; i++)
|
|
||||||
{
|
|
||||||
if (inhinfo[i].inhrelid == oid)
|
|
||||||
{
|
|
||||||
TableInfo *parent;
|
|
||||||
|
|
||||||
parent = findTableByOid(inhinfo[i].inhparent);
|
|
||||||
if (parent == NULL)
|
|
||||||
pg_fatal("failed sanity check, parent OID %u of table \"%s\" (OID %u) not found",
|
|
||||||
inhinfo[i].inhparent,
|
|
||||||
self->dobj.name,
|
|
||||||
oid);
|
|
||||||
self->parents[j++] = parent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
self->parents = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* parseOidArray
|
* parseOidArray
|
||||||
* parse a string of numbers delimited by spaces into a character array
|
* parse a string of numbers delimited by spaces into a character array
|
||||||
|
@ -16180,9 +16180,6 @@ dumpTableAttach(Archive *fout, const TableAttachInfo *attachinfo)
|
|||||||
if (dopt->dataOnly)
|
if (dopt->dataOnly)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(attachinfo->partitionTbl->dobj.dump & DUMP_COMPONENT_DEFINITION))
|
|
||||||
return;
|
|
||||||
|
|
||||||
q = createPQExpBuffer();
|
q = createPQExpBuffer();
|
||||||
|
|
||||||
if (!fout->is_prepared[PREPQUERY_DUMPTABLEATTACH])
|
if (!fout->is_prepared[PREPQUERY_DUMPTABLEATTACH])
|
||||||
|
@ -320,6 +320,9 @@ typedef struct _tableInfo
|
|||||||
bool ispartition; /* is table a partition? */
|
bool ispartition; /* is table a partition? */
|
||||||
bool unsafe_partitions; /* is it an unsafe partitioned table? */
|
bool unsafe_partitions; /* is it an unsafe partitioned table? */
|
||||||
|
|
||||||
|
int numParents; /* number of (immediate) parent tables */
|
||||||
|
struct _tableInfo **parents; /* TableInfos of immediate parents */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These fields are computed only if we decide the table is interesting
|
* These fields are computed only if we decide the table is interesting
|
||||||
* (it's either a table to dump, or a direct parent of a dumpable table).
|
* (it's either a table to dump, or a direct parent of a dumpable table).
|
||||||
@ -351,8 +354,6 @@ typedef struct _tableInfo
|
|||||||
/*
|
/*
|
||||||
* Stuff computed only for dumpable tables.
|
* Stuff computed only for dumpable tables.
|
||||||
*/
|
*/
|
||||||
int numParents; /* number of (immediate) parent tables */
|
|
||||||
struct _tableInfo **parents; /* TableInfos of immediate parents */
|
|
||||||
int numIndexes; /* number of indexes */
|
int numIndexes; /* number of indexes */
|
||||||
struct _indxInfo *indexes; /* indexes */
|
struct _indxInfo *indexes; /* indexes */
|
||||||
struct _tableDataInfo *dataObj; /* TableDataInfo, if dumping its data */
|
struct _tableDataInfo *dataObj; /* TableDataInfo, if dumping its data */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user