Skip to content

Commit ca333f9

Browse files
jeff-daviscoreyhuinkerjeff-davis-aster
authored andcommitted
pg_dump: prepare attribute stats query.
Follow precedent in pg_dump for preparing queries to improve performance. Also, simplify the query by removing unnecessary joins. Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us> Reported-by: Andres Freund <andres@anarazel.de> Co-authored-by: Corey Huinker <corey.huinker@gmail.com> Co-authored-by: Jeff Davis <pgsql@j-davis.com> Discussion: https://postgr.es/m/CADkLM=dRMC6t8gp9GVf6y6E_r5EChQjMAAh_vPyih_zMiq0zvA@mail.gmail.com (cherry picked from commit 6ee3b91)
1 parent 18f9300 commit ca333f9

File tree

2 files changed

+58
-66
lines changed

2 files changed

+58
-66
lines changed

src/bin/pg_dump/pg_backup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ enum _dumpPreparedQueries
7070
PREPQUERY_DUMPOPR,
7171
PREPQUERY_DUMPRANGETYPE,
7272
PREPQUERY_DUMPTABLEATTACH,
73+
PREPQUERY_GETATTRIBUTESTATS,
7374
PREPQUERY_GETCOLUMNACLS,
7475
PREPQUERY_GETDOMAINCONSTRAINTS,
7576
NUM_PREP_QUERIES /* must be last */

src/bin/pg_dump/pg_dump.c

Lines changed: 57 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -9858,10 +9858,8 @@ dumpComment(Archive *fout, const char *type,
98589858
* param_name, param_type
98599859
*/
98609860
static const char *att_stats_arginfo[][2] = {
9861-
{"relation", "regclass"},
98629861
{"attname", "name"},
98639862
{"inherited", "boolean"},
9864-
{"version", "integer"},
98659863
{"null_frac", "float4"},
98669864
{"avg_width", "integer"},
98679865
{"n_distinct", "float4"},
@@ -9877,60 +9875,6 @@ static const char *att_stats_arginfo[][2] = {
98779875
{"range_bounds_histogram", "text"},
98789876
};
98799877

9880-
/*
9881-
* getAttStatsExportQuery --
9882-
*
9883-
* Generate a query that will fetch all attribute (e.g. pg_statistic)
9884-
* stats for a given relation.
9885-
*/
9886-
static void
9887-
getAttStatsExportQuery(PQExpBuffer query, Archive *fout,
9888-
const char *schemaname, const char *relname)
9889-
{
9890-
resetPQExpBuffer(query);
9891-
appendPQExpBuffer(query,
9892-
"SELECT c.oid::regclass AS relation, "
9893-
"s.attname,"
9894-
"s.inherited,"
9895-
"'%u'::integer AS version, "
9896-
"s.null_frac,"
9897-
"s.avg_width,"
9898-
"s.n_distinct,"
9899-
"s.most_common_vals,"
9900-
"s.most_common_freqs,"
9901-
"s.histogram_bounds,"
9902-
"s.correlation,"
9903-
"s.most_common_elems,"
9904-
"s.most_common_elem_freqs,"
9905-
"s.elem_count_histogram,",
9906-
fout->remoteVersion);
9907-
9908-
if (fout->remoteVersion >= 170000)
9909-
appendPQExpBufferStr(query,
9910-
"s.range_length_histogram,"
9911-
"s.range_empty_frac,"
9912-
"s.range_bounds_histogram ");
9913-
else
9914-
appendPQExpBufferStr(query,
9915-
"NULL AS range_length_histogram,"
9916-
"NULL AS range_empty_frac,"
9917-
"NULL AS range_bounds_histogram ");
9918-
9919-
appendPQExpBufferStr(query,
9920-
"FROM pg_stats s "
9921-
"JOIN pg_namespace n "
9922-
"ON n.nspname = s.schemaname "
9923-
"JOIN pg_class c "
9924-
"ON c.relname = s.tablename "
9925-
"AND c.relnamespace = n.oid "
9926-
"WHERE s.schemaname = ");
9927-
appendStringLiteralAH(query, schemaname, fout);
9928-
appendPQExpBufferStr(query, " AND s.tablename = ");
9929-
appendStringLiteralAH(query, relname, fout);
9930-
appendPQExpBufferStr(query, " ORDER BY s.attname, s.inherited");
9931-
}
9932-
9933-
99349878
/*
99359879
* appendNamedArgument --
99369880
*
@@ -9956,17 +9900,17 @@ appendNamedArgument(PQExpBuffer out, Archive *fout, const char *argname,
99569900
* Append a formatted pg_restore_relation_stats statement.
99579901
*/
99589902
static void
9959-
appendRelStatsImport(PQExpBuffer out, Archive *fout, const RelStatsInfo *rsinfo)
9903+
appendRelStatsImport(PQExpBuffer out, Archive *fout, const RelStatsInfo *rsinfo,
9904+
const char *qualified_name)
99609905
{
9961-
const char *qualname = fmtQualifiedId(rsinfo->dobj.namespace->dobj.name, rsinfo->dobj.name);
99629906
char reltuples_str[FLOAT_SHORTEST_DECIMAL_LEN];
99639907

99649908
float_to_shortest_decimal_buf(rsinfo->reltuples, reltuples_str);
99659909

99669910
appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_relation_stats(\n");
9967-
appendPQExpBuffer(out, "\t'relation', '%s'::regclass,\n", qualname);
99689911
appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
99699912
fout->remoteVersion);
9913+
appendPQExpBuffer(out, "\t'relation', '%s'::regclass,\n", qualified_name);
99709914
appendPQExpBuffer(out, "\t'relpages', '%d'::integer,\n", rsinfo->relpages);
99719915
appendPQExpBuffer(out, "\t'reltuples', '%s'::real,\n", reltuples_str);
99729916
appendPQExpBuffer(out, "\t'relallvisible', '%d'::integer\n);\n",
@@ -9979,13 +9923,18 @@ appendRelStatsImport(PQExpBuffer out, Archive *fout, const RelStatsInfo *rsinfo)
99799923
* Append a series of formatted pg_restore_attribute_stats statements.
99809924
*/
99819925
static void
9982-
appendAttStatsImport(PQExpBuffer out, Archive *fout, PGresult *res)
9926+
appendAttStatsImport(PQExpBuffer out, Archive *fout, PGresult *res,
9927+
const char *qualified_name)
99839928
{
99849929
for (int rownum = 0; rownum < PQntuples(res); rownum++)
99859930
{
99869931
const char *sep = "";
99879932

99889933
appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_attribute_stats(\n");
9934+
appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
9935+
fout->remoteVersion);
9936+
appendPQExpBuffer(out, "\t'relation', '%s'::regclass,\n",
9937+
qualified_name);
99899938
for (int argno = 0; argno < lengthof(att_stats_arginfo); argno++)
99909939
{
99919940
const char *argname = att_stats_arginfo[argno][0];
@@ -10050,6 +9999,7 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
100509999
DumpableObject *dobj = (DumpableObject *) &rsinfo->dobj;
1005110000
DumpId *deps = NULL;
1005210001
int ndeps = 0;
10002+
const char *qualified_name;
1005310003

1005410004
/* nothing to do if we are not dumping statistics */
1005510005
if (!fout->dopt->dumpStatistics)
@@ -10065,15 +10015,56 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
1006510015
tag = createPQExpBuffer();
1006610016
appendPQExpBufferStr(tag, fmtId(dobj->name));
1006710017

10068-
out = createPQExpBuffer();
10018+
query = createPQExpBuffer();
10019+
if (!fout->is_prepared[PREPQUERY_GETATTRIBUTESTATS])
10020+
{
10021+
appendPQExpBufferStr(query,
10022+
"PREPARE getAttributeStats(pg_catalog.name, pg_catalog.name) AS\n"
10023+
"SELECT s.attname, s.inherited, "
10024+
"s.null_frac, s.avg_width, s.n_distinct, "
10025+
"s.most_common_vals, s.most_common_freqs, "
10026+
"s.histogram_bounds, s.correlation, "
10027+
"s.most_common_elems, s.most_common_elem_freqs, "
10028+
"s.elem_count_histogram, ");
10029+
10030+
if (fout->remoteVersion >= 170000)
10031+
appendPQExpBufferStr(query,
10032+
"s.range_length_histogram, s.range_empty_frac, "
10033+
"s.range_bounds_histogram ");
10034+
else
10035+
appendPQExpBufferStr(query,
10036+
"NULL AS range_length_histogram,"
10037+
"NULL AS range_empty_frac,"
10038+
"NULL AS range_bounds_histogram ");
1006910039

10070-
appendRelStatsImport(out, fout, rsinfo);
10040+
appendPQExpBufferStr(query,
10041+
"FROM pg_stats s "
10042+
"WHERE s.schemaname = $1 "
10043+
"AND s.tablename = $2 "
10044+
"ORDER BY s.attname, s.inherited");
10045+
10046+
ExecuteSqlStatement(fout, query->data);
10047+
10048+
fout->is_prepared[PREPQUERY_GETATTRIBUTESTATS] = true;
10049+
resetPQExpBuffer(query);
10050+
}
10051+
10052+
appendPQExpBufferStr(query, "EXECUTE getAttributeStats(");
10053+
appendStringLiteralAH(query, dobj->namespace->dobj.name, fout);
10054+
appendPQExpBufferStr(query, ", ");
10055+
appendStringLiteralAH(query, dobj->name, fout);
10056+
appendPQExpBufferStr(query, "); ");
1007110057

10072-
query = createPQExpBuffer();
10073-
getAttStatsExportQuery(query, fout, dobj->namespace->dobj.name,
10074-
dobj->name);
1007510058
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
10076-
appendAttStatsImport(out, fout, res);
10059+
10060+
out = createPQExpBuffer();
10061+
10062+
qualified_name = fmtQualifiedId(rsinfo->dobj.namespace->dobj.name,
10063+
rsinfo->dobj.name);
10064+
10065+
appendRelStatsImport(out, fout, rsinfo, qualified_name);
10066+
appendAttStatsImport(out, fout, res, qualified_name);
10067+
1007710068
PQclear(res);
1007810069

1007910070
ArchiveEntry(fout, nilCatalogId, createDumpId(),

0 commit comments

Comments
 (0)