aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Davis <jdavis@postgresql.org>2025-03-06 19:36:34 -0800
committerJeff Davis <jdavis@postgresql.org>2025-03-06 19:39:14 -0800
commitd611f8b1587b8f30caa7c0da99ae5d28e914d54f (patch)
tree81e8e261c9988b878fd80e095814e8029d53d246
parent19e57f4f78e4354d9a21c284868373d28bb0d368 (diff)
downloadpostgresql-d611f8b1587b8f30caa7c0da99ae5d28e914d54f.tar.gz
postgresql-d611f8b1587b8f30caa7c0da99ae5d28e914d54f.zip
CREATE INDEX: don't update table stats if autovacuum=off.
We previously fixed this for binary upgrade in 71b66171d0, but a similar problem remained when dumping statistics without data. Fix by not opportunistically updating table stats during CREATE INDEX when autovacuum is disabled. For stats to be stable at all, the server needs to be aware that it should not take every opportunity to update stats. Per discussion, autovacuum=off is a signal that the user expects stats to be stable; though if necessary, we could create a more specific mode in the future. Reported-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Discussion: https://postgr.es/m/CAExHW5vf9D+8-a5_BEX3y=2y_xY9hiCxV1=C+FnxDvfprWvkng@mail.gmail.com Discussion: https://postgr.es/m/ca81cbf6e6ea2af838df972801ad4da52640a503.camel%40j-davis.com
-rw-r--r--src/backend/catalog/index.c22
-rw-r--r--src/test/regress/expected/stats_import.out29
-rw-r--r--src/test/regress/sql/stats_import.sql17
3 files changed, 68 insertions, 0 deletions
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 8e1741c81f5..022b9b99b13 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -63,6 +63,7 @@
#include "optimizer/optimizer.h"
#include "parser/parser.h"
#include "pgstat.h"
+#include "postmaster/autovacuum.h"
#include "rewrite/rewriteManip.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
@@ -2841,6 +2842,27 @@ index_update_stats(Relation rel,
update_stats = reltuples >= 0 && !IsBinaryUpgrade;
/*
+ * If autovacuum is off, user may not be expecting table relstats to
+ * change. This can be important when restoring a dump that includes
+ * statistics, as the table statistics may be restored before the index is
+ * created, and we want to preserve the restored table statistics.
+ */
+ if (AutoVacuumingActive())
+ {
+ if (rel->rd_rel->relkind == RELKIND_RELATION ||
+ rel->rd_rel->relkind == RELKIND_TOASTVALUE ||
+ rel->rd_rel->relkind == RELKIND_MATVIEW)
+ {
+ StdRdOptions *options = (StdRdOptions *) rel->rd_options;
+
+ if (options != NULL && !options->autovacuum.enabled)
+ update_stats = false;
+ }
+ }
+ else
+ update_stats = false;
+
+ /*
* Finish I/O and visibility map buffer locks before
* systable_inplace_update_begin() locks the pg_class buffer. The rd_rel
* we modify may differ from rel->rd_rel due to e.g. commit of concurrent
diff --git a/src/test/regress/expected/stats_import.out b/src/test/regress/expected/stats_import.out
index ebba14c6a1d..1f46d5e7854 100644
--- a/src/test/regress/expected/stats_import.out
+++ b/src/test/regress/expected/stats_import.out
@@ -12,7 +12,36 @@ CREATE TABLE stats_import.test(
arange int4range,
tags text[]
) WITH (autovacuum_enabled = false);
+SELECT
+ pg_catalog.pg_restore_relation_stats(
+ 'relation', 'stats_import.test'::regclass,
+ 'relpages', 18::integer,
+ 'reltuples', 21::real,
+ 'relallvisible', 24::integer,
+ 'relallfrozen', 27::integer);
+ pg_restore_relation_stats
+---------------------------
+ t
+(1 row)
+
+-- CREATE INDEX on a table with autovac disabled should not overwrite
+-- stats
CREATE INDEX test_i ON stats_import.test(id);
+SELECT relname, relpages, reltuples, relallvisible, relallfrozen
+FROM pg_class
+WHERE oid = 'stats_import.test'::regclass
+ORDER BY relname;
+ relname | relpages | reltuples | relallvisible | relallfrozen
+---------+----------+-----------+---------------+--------------
+ test | 18 | 21 | 24 | 27
+(1 row)
+
+SELECT pg_clear_relation_stats('stats_import.test'::regclass);
+ pg_clear_relation_stats
+-------------------------
+
+(1 row)
+
--
-- relstats tests
--
diff --git a/src/test/regress/sql/stats_import.sql b/src/test/regress/sql/stats_import.sql
index 8d04ff4f378..0ec590688c2 100644
--- a/src/test/regress/sql/stats_import.sql
+++ b/src/test/regress/sql/stats_import.sql
@@ -15,8 +15,25 @@ CREATE TABLE stats_import.test(
tags text[]
) WITH (autovacuum_enabled = false);
+SELECT
+ pg_catalog.pg_restore_relation_stats(
+ 'relation', 'stats_import.test'::regclass,
+ 'relpages', 18::integer,
+ 'reltuples', 21::real,
+ 'relallvisible', 24::integer,
+ 'relallfrozen', 27::integer);
+
+-- CREATE INDEX on a table with autovac disabled should not overwrite
+-- stats
CREATE INDEX test_i ON stats_import.test(id);
+SELECT relname, relpages, reltuples, relallvisible, relallfrozen
+FROM pg_class
+WHERE oid = 'stats_import.test'::regclass
+ORDER BY relname;
+
+SELECT pg_clear_relation_stats('stats_import.test'::regclass);
+
--
-- relstats tests
--