v2-0001-Leverage-existing-functions-for-relation-stats.patch
text/x-patch
Filename: v2-0001-Leverage-existing-functions-for-relation-stats.patch
Type: text/x-patch
Part: 0
Message:
Re: Statistics Import and Export
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0001
Subject: Leverage existing functions for relation stats.
| File | + | − |
|---|---|---|
| src/bin/pg_dump/pg_dump.c | 49 | 68 |
| src/bin/pg_dump/pg_dump.h | 3 | 0 |
From 95127f6fd82bde843e5840de93678ff784750c8a Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huinker@gmail.com>
Date: Mon, 24 Feb 2025 02:38:22 -0500
Subject: [PATCH v2 1/3] Leverage existing functions for relation stats.
Rather than quer pg_class once per relation in order to fetch relation
stats (reltuples, relpages, relallvisible), instead just add those
fields to the existing queries in getTables() and getIndexes(), then
then store their string representations in RelStatsInfo.
---
src/bin/pg_dump/pg_dump.c | 117 ++++++++++++++++----------------------
src/bin/pg_dump/pg_dump.h | 3 +
2 files changed, 52 insertions(+), 68 deletions(-)
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index afd79287177..a5e7aa73671 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -6814,7 +6814,8 @@ getFuncs(Archive *fout)
*
*/
static RelStatsInfo *
-getRelationStatistics(Archive *fout, DumpableObject *rel, char relkind)
+getRelationStatistics(Archive *fout, DumpableObject *rel, const char *relpages,
+ const char *reltuples, const char *relallvisible, char relkind)
{
if (!fout->dopt->dumpStatistics)
return NULL;
@@ -6839,6 +6840,9 @@ getRelationStatistics(Archive *fout, DumpableObject *rel, char relkind)
dobj->components |= DUMP_COMPONENT_STATISTICS;
dobj->name = pg_strdup(rel->name);
dobj->namespace = rel->namespace;
+ strncpy(info->relpages, relpages,sizeof(info->relpages));
+ strncpy(info->reltuples, reltuples, sizeof(info->reltuples));
+ strncpy(info->relallvisible, relallvisible, sizeof(info->relallvisible));
info->relkind = relkind;
info->postponed_def = false;
@@ -6874,6 +6878,8 @@ getTables(Archive *fout, int *numTables)
int i_relhasindex;
int i_relhasrules;
int i_relpages;
+ int i_reltuples;
+ int i_relallvisible;
int i_toastpages;
int i_owning_tab;
int i_owning_col;
@@ -6921,6 +6927,7 @@ getTables(Archive *fout, int *numTables)
appendPQExpBufferStr(query,
"SELECT c.tableoid, c.oid, c.relname, "
"c.relnamespace, c.relkind, c.reltype, "
+ "c.relpages, c.reltuples, c.relallvisible, "
"c.relowner, "
"c.relchecks, "
"c.relhasindex, c.relhasrules, c.relpages, "
@@ -7088,6 +7095,8 @@ getTables(Archive *fout, int *numTables)
i_relhasindex = PQfnumber(res, "relhasindex");
i_relhasrules = PQfnumber(res, "relhasrules");
i_relpages = PQfnumber(res, "relpages");
+ i_reltuples = PQfnumber(res, "reltuples");
+ i_relallvisible = PQfnumber(res, "relallvisible");
i_toastpages = PQfnumber(res, "toastpages");
i_owning_tab = PQfnumber(res, "owning_tab");
i_owning_col = PQfnumber(res, "owning_col");
@@ -7233,7 +7242,14 @@ getTables(Archive *fout, int *numTables)
/* Add statistics */
if (tblinfo[i].interesting)
- getRelationStatistics(fout, &tblinfo[i].dobj, tblinfo[i].relkind);
+ {
+ char *relpages = PQgetvalue(res, i, i_relpages);
+ char *reltuples = PQgetvalue(res, i, i_reltuples);
+ char *relallvisible = PQgetvalue(res, i, i_relallvisible);
+
+ getRelationStatistics(fout, &tblinfo[i].dobj, relpages, reltuples,
+ relallvisible, tblinfo[i].relkind);
+ }
/*
* Read-lock target tables to make sure they aren't DROPPED or altered
@@ -7499,6 +7515,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
i_oid,
i_indrelid,
i_indexname,
+ i_relpages,
+ i_reltuples,
+ i_relallvisible,
i_parentidx,
i_indexdef,
i_indnkeyatts,
@@ -7552,6 +7571,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
appendPQExpBufferStr(query,
"SELECT t.tableoid, t.oid, i.indrelid, "
"t.relname AS indexname, "
+ "t.relpages, t.reltuples, t.relallvisible, "
"pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
"i.indkey, i.indisclustered, "
"c.contype, c.conname, "
@@ -7659,6 +7679,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
i_oid = PQfnumber(res, "oid");
i_indrelid = PQfnumber(res, "indrelid");
i_indexname = PQfnumber(res, "indexname");
+ i_relpages = PQfnumber(res, "relpages");
+ i_reltuples = PQfnumber(res, "reltuples");
+ i_relallvisible = PQfnumber(res, "relallvisible");
i_parentidx = PQfnumber(res, "parentidx");
i_indexdef = PQfnumber(res, "indexdef");
i_indnkeyatts = PQfnumber(res, "indnkeyatts");
@@ -7725,6 +7748,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
char contype;
char indexkind;
RelStatsInfo *relstats;
+ char *relpages;
+ char *reltuples;
+ char *relallvisible;
indxinfo[j].dobj.objType = DO_INDEX;
indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
@@ -7758,8 +7784,13 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
else
indexkind = RELKIND_PARTITIONED_INDEX;
+ relpages = PQgetvalue(res, j, i_relpages);
+ reltuples = PQgetvalue(res, j, i_reltuples);
+ relallvisible = PQgetvalue(res, j, i_relallvisible);
+
contype = *(PQgetvalue(res, j, i_contype));
- relstats = getRelationStatistics(fout, &indxinfo[j].dobj, indexkind);
+ relstats = getRelationStatistics(fout, &indxinfo[j].dobj, relpages,
+ reltuples, relallvisible, indexkind);
if (contype == 'p' || contype == 'u' || contype == 'x')
{
@@ -10383,18 +10414,6 @@ dumpComment(Archive *fout, const char *type,
catalogId, subid, dumpId, NULL);
}
-/*
- * Tabular description of the parameters to pg_restore_relation_stats()
- * param_name, param_type
- */
-static const char *rel_stats_arginfo[][2] = {
- {"relation", "regclass"},
- {"version", "integer"},
- {"relpages", "integer"},
- {"reltuples", "real"},
- {"relallvisible", "integer"},
-};
-
/*
* Tabular description of the parameters to pg_restore_attribute_stats()
* param_name, param_type
@@ -10419,30 +10438,6 @@ static const char *att_stats_arginfo[][2] = {
{"range_bounds_histogram", "text"},
};
-/*
- * getRelStatsExportQuery --
- *
- * Generate a query that will fetch all relation (e.g. pg_class)
- * stats for a given relation.
- */
-static void
-getRelStatsExportQuery(PQExpBuffer query, Archive *fout,
- const char *schemaname, const char *relname)
-{
- resetPQExpBuffer(query);
- appendPQExpBufferStr(query,
- "SELECT c.oid::regclass AS relation, "
- "current_setting('server_version_num') AS version, "
- "c.relpages, c.reltuples, c.relallvisible "
- "FROM pg_class c "
- "JOIN pg_namespace n "
- "ON n.oid = c.relnamespace "
- "WHERE n.nspname = ");
- appendStringLiteralAH(query, schemaname, fout);
- appendPQExpBufferStr(query, " AND c.relname = ");
- appendStringLiteralAH(query, relname, fout);
-}
-
/*
* getAttStatsExportQuery --
*
@@ -10521,33 +10516,23 @@ appendNamedArgument(PQExpBuffer out, Archive *fout, const char *argname,
* Append a formatted pg_restore_relation_stats statement.
*/
static void
-appendRelStatsImport(PQExpBuffer out, Archive *fout, PGresult *res)
+appendRelStatsImport(PQExpBuffer out, Archive *fout, const RelStatsInfo *rsinfo)
{
- const char *sep = "";
+ const char *qualname = fmtQualifiedId(rsinfo->dobj.namespace->dobj.name, rsinfo->dobj.name);
+ char version[32];
- if (PQntuples(res) == 0)
- return;
+ snprintf(version, sizeof(version), "%d", fout->remoteVersion);
appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_relation_stats(\n");
-
- for (int argno = 0; argno < lengthof(rel_stats_arginfo); argno++)
- {
- const char *argname = rel_stats_arginfo[argno][0];
- const char *argtype = rel_stats_arginfo[argno][1];
- int fieldno = PQfnumber(res, argname);
-
- if (fieldno < 0)
- pg_fatal("relation stats export query missing field '%s'",
- argname);
-
- if (PQgetisnull(res, 0, fieldno))
- continue;
-
- appendPQExpBufferStr(out, sep);
- appendNamedArgument(out, fout, argname, PQgetvalue(res, 0, fieldno), argtype);
-
- sep = ",\n";
- }
+ appendNamedArgument(out, fout, "relation", qualname, "regclass");
+ appendPQExpBufferStr(out, ",\n");
+ appendNamedArgument(out, fout, "version", version, "integer");
+ appendPQExpBufferStr(out, ",\n");
+ appendNamedArgument(out, fout, "relpages", rsinfo->relpages, "integer");
+ appendPQExpBufferStr(out, ",\n");
+ appendNamedArgument(out, fout, "reltuples", rsinfo->reltuples, "real");
+ appendPQExpBufferStr(out, ",\n");
+ appendNamedArgument(out, fout, "relallvisible", rsinfo->relallvisible, "integer");
appendPQExpBufferStr(out, "\n);\n");
}
@@ -10643,15 +10628,11 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
tag = createPQExpBuffer();
appendPQExpBufferStr(tag, fmtId(dobj->name));
- query = createPQExpBuffer();
out = createPQExpBuffer();
- getRelStatsExportQuery(query, fout, dobj->namespace->dobj.name,
- dobj->name);
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
- appendRelStatsImport(out, fout, res);
- PQclear(res);
+ appendRelStatsImport(out, fout, rsinfo);
+ query = createPQExpBuffer();
getAttStatsExportQuery(query, fout, dobj->namespace->dobj.name,
dobj->name);
res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index f08f5905aa3..1ab134ae414 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -438,6 +438,9 @@ typedef struct _indexAttachInfo
typedef struct _relStatsInfo
{
DumpableObject dobj;
+ char relpages[32];
+ char reltuples[32];
+ char relallvisible[32];
char relkind; /* 'r', 'm', 'i', etc */
bool postponed_def; /* stats must be postponed into post-data */
} RelStatsInfo;
base-commit: 2421e9a51d20bb83154e54a16ce628f9249fa907
--
2.48.1