Skip to content

Commit 18f9300

Browse files
jeff-daviscoreyhuinkerjeff-davis-aster
authored andcommitted
Avoid unnecessary relation stats query in pg_dump.
The few fields we need can be easily collected in getTables() and getIndexes() and stored in RelStatsInfo. 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=f0a43aTd88xW4xCFayEF25g-7hTrHX_WhV40HyocsUGg@mail.gmail.com (cherry picked from commit 8f42718)
1 parent f7ab5b3 commit 18f9300

File tree

2 files changed

+64
-86
lines changed

2 files changed

+64
-86
lines changed

src/bin/pg_dump/pg_dump.c

Lines changed: 60 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "catalog/pg_trigger_d.h"
5656
#include "catalog/pg_type_d.h"
5757
#include "common/connect.h"
58+
#include "common/shortest_dec.h"
5859
#include "dumputils.h"
5960
#include "fe_utils/option_utils.h"
6061
#include "fe_utils/string_utils.h"
@@ -432,6 +433,9 @@ main(int argc, char **argv)
432433
pg_logging_set_level(PG_LOG_WARNING);
433434
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
434435

436+
/* ensure that locale does not affect floating point interpretation */
437+
setlocale(LC_NUMERIC, "C");
438+
435439
/*
436440
* Initialize what we need for parallel execution, especially for thread
437441
* support on Windows.
@@ -6289,7 +6293,8 @@ getFuncs(Archive *fout, int *numFuncs)
62896293
*
62906294
*/
62916295
static RelStatsInfo *
6292-
getRelationStatistics(Archive *fout, DumpableObject *rel, char relkind)
6296+
getRelationStatistics(Archive *fout, DumpableObject *rel, int32 relpages,
6297+
float reltuples, int32 relallvisible, char relkind)
62936298
{
62946299
if (!fout->dopt->dumpStatistics)
62956300
return NULL;
@@ -6314,6 +6319,9 @@ getRelationStatistics(Archive *fout, DumpableObject *rel, char relkind)
63146319
dobj->components |= DUMP_COMPONENT_STATISTICS;
63156320
dobj->name = pg_strdup(rel->name);
63166321
dobj->namespace = rel->namespace;
6322+
info->relpages = relpages;
6323+
info->reltuples = reltuples;
6324+
info->relallvisible = relallvisible;
63176325
info->relkind = relkind;
63186326
info->postponed_def = false;
63196327

@@ -6349,6 +6357,8 @@ getTables(Archive *fout, int *numTables)
63496357
int i_relhasindex;
63506358
int i_relhasrules;
63516359
int i_relpages;
6360+
int i_reltuples;
6361+
int i_relallvisible;
63526362
int i_toastpages;
63536363
int i_owning_tab;
63546364
int i_owning_col;
@@ -6399,7 +6409,7 @@ getTables(Archive *fout, int *numTables)
63996409
"c.relowner, "
64006410
"c.relchecks, "
64016411
"c.relhasindex, c.relhasrules, c.relpages, "
6402-
"c.relhastriggers, "
6412+
"c.reltuples, c.relallvisible, c.relhastriggers, "
64036413
"c.relpersistence, "
64046414
"c.reloftype, "
64056415
"c.relacl, "
@@ -6563,6 +6573,8 @@ getTables(Archive *fout, int *numTables)
65636573
i_relhasindex = PQfnumber(res, "relhasindex");
65646574
i_relhasrules = PQfnumber(res, "relhasrules");
65656575
i_relpages = PQfnumber(res, "relpages");
6576+
i_reltuples = PQfnumber(res, "reltuples");
6577+
i_relallvisible = PQfnumber(res, "relallvisible");
65666578
i_toastpages = PQfnumber(res, "toastpages");
65676579
i_owning_tab = PQfnumber(res, "owning_tab");
65686580
i_owning_col = PQfnumber(res, "owning_col");
@@ -6607,6 +6619,9 @@ getTables(Archive *fout, int *numTables)
66076619

66086620
for (i = 0; i < ntups; i++)
66096621
{
6622+
float reltuples = strtof(PQgetvalue(res, i, i_reltuples), NULL);
6623+
int32 relallvisible = atoi(PQgetvalue(res, i, i_relallvisible));
6624+
66106625
tblinfo[i].dobj.objType = DO_TABLE;
66116626
tblinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_reltableoid));
66126627
tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid));
@@ -6706,7 +6721,8 @@ getTables(Archive *fout, int *numTables)
67066721

67076722
/* Add statistics */
67086723
if (tblinfo[i].interesting)
6709-
getRelationStatistics(fout, &tblinfo[i].dobj, tblinfo[i].relkind);
6724+
getRelationStatistics(fout, &tblinfo[i].dobj, tblinfo[i].relpages,
6725+
reltuples, relallvisible, tblinfo[i].relkind);
67106726

67116727
/*
67126728
* Read-lock target tables to make sure they aren't DROPPED or altered
@@ -6948,6 +6964,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
69486964
i_oid,
69496965
i_indrelid,
69506966
i_indexname,
6967+
i_relpages,
6968+
i_reltuples,
6969+
i_relallvisible,
69516970
i_parentidx,
69526971
i_indexdef,
69536972
i_indnkeyatts,
@@ -7000,6 +7019,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
70007019
appendPQExpBuffer(query,
70017020
"SELECT t.tableoid, t.oid, i.indrelid, "
70027021
"t.relname AS indexname, "
7022+
"t.relpages, t.reltuples, t.relallvisible, "
70037023
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
70047024
"i.indkey, i.indisclustered, "
70057025
"c.contype, c.conname, "
@@ -7100,6 +7120,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
71007120
i_oid = PQfnumber(res, "oid");
71017121
i_indrelid = PQfnumber(res, "indrelid");
71027122
i_indexname = PQfnumber(res, "indexname");
7123+
i_relpages = PQfnumber(res, "relpages");
7124+
i_reltuples = PQfnumber(res, "reltuples");
7125+
i_relallvisible = PQfnumber(res, "relallvisible");
71037126
i_parentidx = PQfnumber(res, "parentidx");
71047127
i_indexdef = PQfnumber(res, "indexdef");
71057128
i_indnkeyatts = PQfnumber(res, "indnkeyatts");
@@ -7165,6 +7188,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
71657188
char contype;
71667189
char indexkind;
71677190
RelStatsInfo *relstats;
7191+
int32 relpages = atoi(PQgetvalue(res, j, i_relpages));
7192+
float reltuples = strtof(PQgetvalue(res, j, i_reltuples), NULL);
7193+
int32 relallvisible = atoi(PQgetvalue(res, j, i_relallvisible));
71687194

71697195
indxinfo[j].dobj.objType = DO_INDEX;
71707196
indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
@@ -7199,7 +7225,8 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
71997225
indexkind = RELKIND_PARTITIONED_INDEX;
72007226

72017227
contype = *(PQgetvalue(res, j, i_contype));
7202-
relstats = getRelationStatistics(fout, &indxinfo[j].dobj, indexkind);
7228+
relstats = getRelationStatistics(fout, &indxinfo[j].dobj, relpages,
7229+
reltuples, relallvisible, indexkind);
72037230

72047231
if (contype == 'p' || contype == 'u' || contype == 'x')
72057232
{
@@ -9826,18 +9853,6 @@ dumpComment(Archive *fout, const char *type,
98269853
catalogId, subid, dumpId, NULL);
98279854
}
98289855

9829-
/*
9830-
* Tabular description of the parameters to pg_restore_relation_stats()
9831-
* param_name, param_type
9832-
*/
9833-
static const char *rel_stats_arginfo[][2] = {
9834-
{"relation", "regclass"},
9835-
{"version", "integer"},
9836-
{"relpages", "integer"},
9837-
{"reltuples", "real"},
9838-
{"relallvisible", "integer"},
9839-
};
9840-
98419856
/*
98429857
* Tabular description of the parameters to pg_restore_attribute_stats()
98439858
* param_name, param_type
@@ -9862,30 +9877,6 @@ static const char *att_stats_arginfo[][2] = {
98629877
{"range_bounds_histogram", "text"},
98639878
};
98649879

9865-
/*
9866-
* getRelStatsExportQuery --
9867-
*
9868-
* Generate a query that will fetch all relation (e.g. pg_class)
9869-
* stats for a given relation.
9870-
*/
9871-
static void
9872-
getRelStatsExportQuery(PQExpBuffer query, Archive *fout,
9873-
const char *schemaname, const char *relname)
9874-
{
9875-
resetPQExpBuffer(query);
9876-
appendPQExpBufferStr(query,
9877-
"SELECT c.oid::regclass AS relation, "
9878-
"current_setting('server_version_num') AS version, "
9879-
"c.relpages, c.reltuples, c.relallvisible "
9880-
"FROM pg_class c "
9881-
"JOIN pg_namespace n "
9882-
"ON n.oid = c.relnamespace "
9883-
"WHERE n.nspname = ");
9884-
appendStringLiteralAH(query, schemaname, fout);
9885-
appendPQExpBufferStr(query, " AND c.relname = ");
9886-
appendStringLiteralAH(query, relname, fout);
9887-
}
9888-
98899880
/*
98909881
* getAttStatsExportQuery --
98919882
*
@@ -9897,21 +9888,22 @@ getAttStatsExportQuery(PQExpBuffer query, Archive *fout,
98979888
const char *schemaname, const char *relname)
98989889
{
98999890
resetPQExpBuffer(query);
9900-
appendPQExpBufferStr(query,
9901-
"SELECT c.oid::regclass AS relation, "
9902-
"s.attname,"
9903-
"s.inherited,"
9904-
"current_setting('server_version_num') AS version, "
9905-
"s.null_frac,"
9906-
"s.avg_width,"
9907-
"s.n_distinct,"
9908-
"s.most_common_vals,"
9909-
"s.most_common_freqs,"
9910-
"s.histogram_bounds,"
9911-
"s.correlation,"
9912-
"s.most_common_elems,"
9913-
"s.most_common_elem_freqs,"
9914-
"s.elem_count_histogram,");
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);
99159907

99169908
if (fout->remoteVersion >= 170000)
99179909
appendPQExpBufferStr(query,
@@ -9964,34 +9956,21 @@ appendNamedArgument(PQExpBuffer out, Archive *fout, const char *argname,
99649956
* Append a formatted pg_restore_relation_stats statement.
99659957
*/
99669958
static void
9967-
appendRelStatsImport(PQExpBuffer out, Archive *fout, PGresult *res)
9959+
appendRelStatsImport(PQExpBuffer out, Archive *fout, const RelStatsInfo *rsinfo)
99689960
{
9969-
const char *sep = "";
9961+
const char *qualname = fmtQualifiedId(rsinfo->dobj.namespace->dobj.name, rsinfo->dobj.name);
9962+
char reltuples_str[FLOAT_SHORTEST_DECIMAL_LEN];
99709963

9971-
if (PQntuples(res) == 0)
9972-
return;
9964+
float_to_shortest_decimal_buf(rsinfo->reltuples, reltuples_str);
99739965

99749966
appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_relation_stats(\n");
9975-
9976-
for (int argno = 0; argno < lengthof(rel_stats_arginfo); argno++)
9977-
{
9978-
const char *argname = rel_stats_arginfo[argno][0];
9979-
const char *argtype = rel_stats_arginfo[argno][1];
9980-
int fieldno = PQfnumber(res, argname);
9981-
9982-
if (fieldno < 0)
9983-
pg_fatal("relation stats export query missing field '%s'",
9984-
argname);
9985-
9986-
if (PQgetisnull(res, 0, fieldno))
9987-
continue;
9988-
9989-
appendPQExpBufferStr(out, sep);
9990-
appendNamedArgument(out, fout, argname, PQgetvalue(res, 0, fieldno), argtype);
9991-
9992-
sep = ",\n";
9993-
}
9994-
appendPQExpBufferStr(out, "\n);\n");
9967+
appendPQExpBuffer(out, "\t'relation', '%s'::regclass,\n", qualname);
9968+
appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
9969+
fout->remoteVersion);
9970+
appendPQExpBuffer(out, "\t'relpages', '%d'::integer,\n", rsinfo->relpages);
9971+
appendPQExpBuffer(out, "\t'reltuples', '%s'::real,\n", reltuples_str);
9972+
appendPQExpBuffer(out, "\t'relallvisible', '%d'::integer\n);\n",
9973+
rsinfo->relallvisible);
99959974
}
99969975

99979976
/*
@@ -10086,15 +10065,11 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
1008610065
tag = createPQExpBuffer();
1008710066
appendPQExpBufferStr(tag, fmtId(dobj->name));
1008810067

10089-
query = createPQExpBuffer();
1009010068
out = createPQExpBuffer();
1009110069

10092-
getRelStatsExportQuery(query, fout, dobj->namespace->dobj.name,
10093-
dobj->name);
10094-
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
10095-
appendRelStatsImport(out, fout, res);
10096-
PQclear(res);
10070+
appendRelStatsImport(out, fout, rsinfo);
1009710071

10072+
query = createPQExpBuffer();
1009810073
getAttStatsExportQuery(query, fout, dobj->namespace->dobj.name,
1009910074
dobj->name);
1010010075
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);

src/bin/pg_dump/pg_dump.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ typedef struct _tableInfo
325325
Oid owning_tab; /* OID of table owning sequence */
326326
int owning_col; /* attr # of column owning sequence */
327327
bool is_identity_sequence;
328-
int relpages; /* table's size in pages (from pg_class) */
328+
int32 relpages; /* table's size in pages (from pg_class) */
329329
int toastpages; /* toast table's size in pages, if any */
330330

331331
bool interesting; /* true if need to collect more data */
@@ -431,6 +431,9 @@ typedef struct _indexAttachInfo
431431
typedef struct _relStatsInfo
432432
{
433433
DumpableObject dobj;
434+
int32 relpages;
435+
float reltuples;
436+
int32 relallvisible;
434437
char relkind; /* 'r', 'm', 'i', etc */
435438
bool postponed_def; /* stats must be postponed into post-data */
436439
} RelStatsInfo;

0 commit comments

Comments
 (0)