Cache the results of format_type() queries in pg_dump.
There's long been a "TODO: there might be some value in caching the results" annotation on pg_dump's getFormattedTypeName function; but we hadn't gotten around to checking what it was costing us to repetitively look up type names. It turns out that when dumping the current regression database, about 10% of the total number of queries issued are duplicative format_type() queries. However, Hubert Depesz Lubaczewski reported a not-unusual case where these account for over half of the queries issued by pg_dump. Individually these queries aren't expensive, but when network lag is a factor, they add up to a problem. We can very easily add some caching to getFormattedTypeName to solve it. Since this is such a simple fix and can have a visible performance benefit, back-patch to all supported branches. Discussion: https://postgr.es/m/20210826084430.GA26282@depesz.com
This commit is contained in:
parent
bce24d1edb
commit
c4b298ee15
@ -4939,6 +4939,7 @@ getTypes(Archive *fout, int *numTypes)
|
|||||||
tyinfo[i].dobj.namespace =
|
tyinfo[i].dobj.namespace =
|
||||||
findNamespace(fout,
|
findNamespace(fout,
|
||||||
atooid(PQgetvalue(res, i, i_typnamespace)));
|
atooid(PQgetvalue(res, i, i_typnamespace)));
|
||||||
|
tyinfo[i].ftypname = NULL; /* may get filled later */
|
||||||
tyinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
|
tyinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
|
||||||
tyinfo[i].typacl = pg_strdup(PQgetvalue(res, i, i_typacl));
|
tyinfo[i].typacl = pg_strdup(PQgetvalue(res, i, i_typacl));
|
||||||
tyinfo[i].rtypacl = pg_strdup(PQgetvalue(res, i, i_rtypacl));
|
tyinfo[i].rtypacl = pg_strdup(PQgetvalue(res, i, i_rtypacl));
|
||||||
@ -18480,12 +18481,11 @@ findDumpableDependencies(ArchiveHandle *AH, DumpableObject *dobj,
|
|||||||
*
|
*
|
||||||
* This does not guarantee to schema-qualify the output, so it should not
|
* This does not guarantee to schema-qualify the output, so it should not
|
||||||
* be used to create the target object name for CREATE or ALTER commands.
|
* be used to create the target object name for CREATE or ALTER commands.
|
||||||
*
|
|
||||||
* TODO: there might be some value in caching the results.
|
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts)
|
getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts)
|
||||||
{
|
{
|
||||||
|
TypeInfo *typeInfo;
|
||||||
char *result;
|
char *result;
|
||||||
PQExpBuffer query;
|
PQExpBuffer query;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
@ -18502,6 +18502,11 @@ getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts)
|
|||||||
return pg_strdup("NONE");
|
return pg_strdup("NONE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* see if we have the result cached in the type's TypeInfo record */
|
||||||
|
typeInfo = findTypeByOid(oid);
|
||||||
|
if (typeInfo && typeInfo->ftypname)
|
||||||
|
return pg_strdup(typeInfo->ftypname);
|
||||||
|
|
||||||
query = createPQExpBuffer();
|
query = createPQExpBuffer();
|
||||||
appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)",
|
appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%u'::pg_catalog.oid, NULL)",
|
||||||
oid);
|
oid);
|
||||||
@ -18514,6 +18519,10 @@ getFormattedTypeName(Archive *fout, Oid oid, OidOptions opts)
|
|||||||
PQclear(res);
|
PQclear(res);
|
||||||
destroyPQExpBuffer(query);
|
destroyPQExpBuffer(query);
|
||||||
|
|
||||||
|
/* cache a copy for later requests */
|
||||||
|
if (typeInfo)
|
||||||
|
typeInfo->ftypname = pg_strdup(result);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,9 +167,11 @@ typedef struct _typeInfo
|
|||||||
DumpableObject dobj;
|
DumpableObject dobj;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: dobj.name is the pg_type.typname entry. format_type() might
|
* Note: dobj.name is the raw pg_type.typname entry. ftypname is the
|
||||||
* produce something different than typname
|
* result of format_type(), which will be quoted if needed, and might be
|
||||||
|
* schema-qualified too.
|
||||||
*/
|
*/
|
||||||
|
char *ftypname;
|
||||||
char *rolname; /* name of owner, or empty string */
|
char *rolname; /* name of owner, or empty string */
|
||||||
char *typacl;
|
char *typacl;
|
||||||
char *rtypacl;
|
char *rtypacl;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user