v6-0004-Avoid-getAttributeStats-call-for-indexes-without-.patch
text/x-patch
Filename: v6-0004-Avoid-getAttributeStats-call-for-indexes-without-.patch
Type: text/x-patch
Part: 2
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 v6-0004
Subject: Avoid getAttributeStats() call for indexes without an expression column.
| File | + | − |
|---|---|---|
| src/bin/pg_dump/pg_dump.c | 122 | 107 |
From 5ea8a35a1d6db14046bb2fb76dfcdddb1bcf9479 Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huinker@gmail.com>
Date: Wed, 5 Mar 2025 22:40:40 -0500
Subject: [PATCH v6 4/4] Avoid getAttributeStats() call for indexes without an
expression column.
---
src/bin/pg_dump/pg_dump.c | 229 ++++++++++++++++++++------------------
1 file changed, 122 insertions(+), 107 deletions(-)
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 6cf2c7d1fe4..0cc2a65caa3 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -10487,7 +10487,6 @@ static void
dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
{
const DumpableObject *dobj = &rsinfo->dobj;
- PGresult *res;
PQExpBuffer query;
PQExpBuffer out;
DumpId *deps = NULL;
@@ -10508,11 +10507,22 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
int i_range_length_histogram;
int i_range_empty_frac;
int i_range_bounds_histogram;
+ bool can_have_attrstats = true;
/* nothing to do if we are not dumping statistics */
if (!fout->dopt->dumpStatistics)
return;
+ /*
+ * Indexes can only have statistics for expression columns.
+ */
+ if ((rsinfo->relkind == RELKIND_INDEX) ||
+ (rsinfo->relkind == RELKIND_PARTITIONED_INDEX))
+ {
+ if (rsinfo->nindAttNames == 0)
+ can_have_attrstats = false;
+ }
+
/* dependent on the relation definition, if doing schema */
if (fout->dopt->dumpSchema)
{
@@ -10573,127 +10583,132 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
appendPQExpBuffer(out, "\t'relallvisible', '%d'::integer\n);\n",
rsinfo->relallvisible);
- /* fetch attribute stats */
- appendPQExpBufferStr(query, "EXECUTE getAttributeStats(");
- appendStringLiteralAH(query, dobj->namespace->dobj.name, fout);
- appendPQExpBufferStr(query, ", ");
- appendStringLiteralAH(query, dobj->name, fout);
- appendPQExpBufferStr(query, ");");
-
- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
-
- i_attname = PQfnumber(res, "attname");
- i_inherited = PQfnumber(res, "inherited");
- i_null_frac = PQfnumber(res, "null_frac");
- i_avg_width = PQfnumber(res, "avg_width");
- i_n_distinct = PQfnumber(res, "n_distinct");
- i_most_common_vals = PQfnumber(res, "most_common_vals");
- i_most_common_freqs = PQfnumber(res, "most_common_freqs");
- i_histogram_bounds = PQfnumber(res, "histogram_bounds");
- i_correlation = PQfnumber(res, "correlation");
- i_most_common_elems = PQfnumber(res, "most_common_elems");
- i_most_common_elem_freqs = PQfnumber(res, "most_common_elem_freqs");
- i_elem_count_histogram = PQfnumber(res, "elem_count_histogram");
- i_range_length_histogram = PQfnumber(res, "range_length_histogram");
- i_range_empty_frac = PQfnumber(res, "range_empty_frac");
- i_range_bounds_histogram = PQfnumber(res, "range_bounds_histogram");
-
- /* restore attribute stats */
- for (int rownum = 0; rownum < PQntuples(res); rownum++)
+ if (can_have_attrstats)
{
- const char *attname;
+ PGresult *res;
- appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_attribute_stats(\n");
- appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
- fout->remoteVersion);
- appendPQExpBufferStr(out, "\t'schemaname', ");
- appendStringLiteralAH(out, rsinfo->dobj.namespace->dobj.name, fout);
- appendPQExpBufferStr(out, ",\n\t'relname', ");
- appendStringLiteralAH(out, rsinfo->dobj.name, fout);
+ /* fetch attribute stats */
+ appendPQExpBufferStr(query, "EXECUTE getAttributeStats(");
+ appendStringLiteralAH(query, dobj->namespace->dobj.name, fout);
+ appendPQExpBufferStr(query, ", ");
+ appendStringLiteralAH(query, dobj->name, fout);
+ appendPQExpBufferStr(query, ");");
- if (PQgetisnull(res, rownum, i_attname))
- pg_fatal("attname cannot be NULL");
- attname = PQgetvalue(res, rownum, i_attname);
+ res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
- /*
- * Indexes look up attname in indAttNames to derive attnum, all others
- * use attname directly. We must specify attnum for indexes, since
- * their attnames are not necessarily stable across dump/reload.
- */
- if (rsinfo->nindAttNames == 0)
+ i_attname = PQfnumber(res, "attname");
+ i_inherited = PQfnumber(res, "inherited");
+ i_null_frac = PQfnumber(res, "null_frac");
+ i_avg_width = PQfnumber(res, "avg_width");
+ i_n_distinct = PQfnumber(res, "n_distinct");
+ i_most_common_vals = PQfnumber(res, "most_common_vals");
+ i_most_common_freqs = PQfnumber(res, "most_common_freqs");
+ i_histogram_bounds = PQfnumber(res, "histogram_bounds");
+ i_correlation = PQfnumber(res, "correlation");
+ i_most_common_elems = PQfnumber(res, "most_common_elems");
+ i_most_common_elem_freqs = PQfnumber(res, "most_common_elem_freqs");
+ i_elem_count_histogram = PQfnumber(res, "elem_count_histogram");
+ i_range_length_histogram = PQfnumber(res, "range_length_histogram");
+ i_range_empty_frac = PQfnumber(res, "range_empty_frac");
+ i_range_bounds_histogram = PQfnumber(res, "range_bounds_histogram");
+
+ /* restore attribute stats */
+ for (int rownum = 0; rownum < PQntuples(res); rownum++)
{
- appendPQExpBuffer(out, ",\n\t'attname', ");
- appendStringLiteralAH(out, attname, fout);
- }
- else
- {
- bool found = false;
+ const char *attname;
- for (int i = 0; i < rsinfo->nindAttNames; i++)
+ appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_attribute_stats(\n");
+ appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
+ fout->remoteVersion);
+ appendPQExpBufferStr(out, "\t'schemaname', ");
+ appendStringLiteralAH(out, rsinfo->dobj.namespace->dobj.name, fout);
+ appendPQExpBufferStr(out, ",\n\t'relname', ");
+ appendStringLiteralAH(out, rsinfo->dobj.name, fout);
+
+ if (PQgetisnull(res, rownum, i_attname))
+ pg_fatal("attname cannot be NULL");
+ attname = PQgetvalue(res, rownum, i_attname);
+
+ /*
+ * Indexes look up attname in indAttNames to derive attnum, all others
+ * use attname directly. We must specify attnum for indexes, since
+ * their attnames are not necessarily stable across dump/reload.
+ */
+ if (rsinfo->nindAttNames == 0)
{
- if (strcmp(attname, rsinfo->indAttNames[i]) == 0)
+ appendPQExpBuffer(out, ",\n\t'attname', ");
+ appendStringLiteralAH(out, attname, fout);
+ }
+ else
+ {
+ bool found = false;
+
+ for (int i = 0; i < rsinfo->nindAttNames; i++)
{
- appendPQExpBuffer(out, ",\n\t'attnum', '%d'::smallint",
- i + 1);
- found = true;
- break;
+ if (strcmp(attname, rsinfo->indAttNames[i]) == 0)
+ {
+ appendPQExpBuffer(out, ",\n\t'attnum', '%d'::smallint",
+ i + 1);
+ found = true;
+ break;
+ }
}
+
+ if (!found)
+ pg_fatal("could not find index attname \"%s\"", attname);
}
- if (!found)
- pg_fatal("could not find index attname \"%s\"", attname);
+ if (!PQgetisnull(res, rownum, i_inherited))
+ appendNamedArgument(out, fout, "inherited", "boolean",
+ PQgetvalue(res, rownum, i_inherited));
+ if (!PQgetisnull(res, rownum, i_null_frac))
+ appendNamedArgument(out, fout, "null_frac", "real",
+ PQgetvalue(res, rownum, i_null_frac));
+ if (!PQgetisnull(res, rownum, i_avg_width))
+ appendNamedArgument(out, fout, "avg_width", "integer",
+ PQgetvalue(res, rownum, i_avg_width));
+ if (!PQgetisnull(res, rownum, i_n_distinct))
+ appendNamedArgument(out, fout, "n_distinct", "real",
+ PQgetvalue(res, rownum, i_n_distinct));
+ if (!PQgetisnull(res, rownum, i_most_common_vals))
+ appendNamedArgument(out, fout, "most_common_vals", "text",
+ PQgetvalue(res, rownum, i_most_common_vals));
+ if (!PQgetisnull(res, rownum, i_most_common_freqs))
+ appendNamedArgument(out, fout, "most_common_freqs", "real[]",
+ PQgetvalue(res, rownum, i_most_common_freqs));
+ if (!PQgetisnull(res, rownum, i_histogram_bounds))
+ appendNamedArgument(out, fout, "histogram_bounds", "text",
+ PQgetvalue(res, rownum, i_histogram_bounds));
+ if (!PQgetisnull(res, rownum, i_correlation))
+ appendNamedArgument(out, fout, "correlation", "real",
+ PQgetvalue(res, rownum, i_correlation));
+ if (!PQgetisnull(res, rownum, i_most_common_elems))
+ appendNamedArgument(out, fout, "most_common_elems", "text",
+ PQgetvalue(res, rownum, i_most_common_elems));
+ if (!PQgetisnull(res, rownum, i_most_common_elem_freqs))
+ appendNamedArgument(out, fout, "most_common_elem_freqs", "real[]",
+ PQgetvalue(res, rownum, i_most_common_elem_freqs));
+ if (!PQgetisnull(res, rownum, i_elem_count_histogram))
+ appendNamedArgument(out, fout, "elem_count_histogram", "real[]",
+ PQgetvalue(res, rownum, i_elem_count_histogram));
+ if (fout->remoteVersion >= 170000)
+ {
+ if (!PQgetisnull(res, rownum, i_range_length_histogram))
+ appendNamedArgument(out, fout, "range_length_histogram", "text",
+ PQgetvalue(res, rownum, i_range_length_histogram));
+ if (!PQgetisnull(res, rownum, i_range_empty_frac))
+ appendNamedArgument(out, fout, "range_empty_frac", "real",
+ PQgetvalue(res, rownum, i_range_empty_frac));
+ if (!PQgetisnull(res, rownum, i_range_bounds_histogram))
+ appendNamedArgument(out, fout, "range_bounds_histogram", "text",
+ PQgetvalue(res, rownum, i_range_bounds_histogram));
+ }
+ appendPQExpBufferStr(out, "\n);\n");
}
- if (!PQgetisnull(res, rownum, i_inherited))
- appendNamedArgument(out, fout, "inherited", "boolean",
- PQgetvalue(res, rownum, i_inherited));
- if (!PQgetisnull(res, rownum, i_null_frac))
- appendNamedArgument(out, fout, "null_frac", "real",
- PQgetvalue(res, rownum, i_null_frac));
- if (!PQgetisnull(res, rownum, i_avg_width))
- appendNamedArgument(out, fout, "avg_width", "integer",
- PQgetvalue(res, rownum, i_avg_width));
- if (!PQgetisnull(res, rownum, i_n_distinct))
- appendNamedArgument(out, fout, "n_distinct", "real",
- PQgetvalue(res, rownum, i_n_distinct));
- if (!PQgetisnull(res, rownum, i_most_common_vals))
- appendNamedArgument(out, fout, "most_common_vals", "text",
- PQgetvalue(res, rownum, i_most_common_vals));
- if (!PQgetisnull(res, rownum, i_most_common_freqs))
- appendNamedArgument(out, fout, "most_common_freqs", "real[]",
- PQgetvalue(res, rownum, i_most_common_freqs));
- if (!PQgetisnull(res, rownum, i_histogram_bounds))
- appendNamedArgument(out, fout, "histogram_bounds", "text",
- PQgetvalue(res, rownum, i_histogram_bounds));
- if (!PQgetisnull(res, rownum, i_correlation))
- appendNamedArgument(out, fout, "correlation", "real",
- PQgetvalue(res, rownum, i_correlation));
- if (!PQgetisnull(res, rownum, i_most_common_elems))
- appendNamedArgument(out, fout, "most_common_elems", "text",
- PQgetvalue(res, rownum, i_most_common_elems));
- if (!PQgetisnull(res, rownum, i_most_common_elem_freqs))
- appendNamedArgument(out, fout, "most_common_elem_freqs", "real[]",
- PQgetvalue(res, rownum, i_most_common_elem_freqs));
- if (!PQgetisnull(res, rownum, i_elem_count_histogram))
- appendNamedArgument(out, fout, "elem_count_histogram", "real[]",
- PQgetvalue(res, rownum, i_elem_count_histogram));
- if (fout->remoteVersion >= 170000)
- {
- if (!PQgetisnull(res, rownum, i_range_length_histogram))
- appendNamedArgument(out, fout, "range_length_histogram", "text",
- PQgetvalue(res, rownum, i_range_length_histogram));
- if (!PQgetisnull(res, rownum, i_range_empty_frac))
- appendNamedArgument(out, fout, "range_empty_frac", "real",
- PQgetvalue(res, rownum, i_range_empty_frac));
- if (!PQgetisnull(res, rownum, i_range_bounds_histogram))
- appendNamedArgument(out, fout, "range_bounds_histogram", "text",
- PQgetvalue(res, rownum, i_range_bounds_histogram));
- }
- appendPQExpBufferStr(out, "\n);\n");
+ PQclear(res);
}
- PQclear(res);
-
ArchiveEntry(fout, nilCatalogId, createDumpId(),
ARCHIVE_OPTS(.tag = dobj->name,
.namespace = dobj->namespace->dobj.name,
--
2.48.1