diff options
author | Michael Paquier <michael@paquier.xyz> | 2020-11-01 21:22:07 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2020-11-01 21:22:07 +0900 |
commit | b17ff07aa3eb142d2cde2ea00e4a4e8f63686f96 (patch) | |
tree | 4a0e8b7b6f6584f0776963da80f072b4b7249363 /src/backend | |
parent | aecaa04418f39c32adb3dbf91c4aa7f6e175f01c (diff) | |
download | postgresql-b17ff07aa3eb142d2cde2ea00e4a4e8f63686f96.tar.gz postgresql-b17ff07aa3eb142d2cde2ea00e4a4e8f63686f96.zip |
Preserve index data in pg_statistic across REINDEX CONCURRENTLY
Statistics associated to an index got lost after running REINDEX
CONCURRENTLY, while the non-concurrent case preserves these correctly.
The concurrent and non-concurrent operations need to be consistent for
the end-user, and missing statistics would force to wait for a new
analyze to happen, which could take some time depending on the activity
of the existing autovacuum workers. This issue is fixed by copying any
existing entries in pg_statistic associated to the old index to the new
one. Note that this copy is already done with the data of the index in
the stats collector.
Reported-by: FabrÃzio de Royes Mello
Author: Michael Paquier, FabrÃzio de Royes Mello
Reviewed-by: Justin Pryzby
Discussion: https://postgr.es/m/CAFcNs+qpFPmiHd1oTXvcPdvAHicJDA9qBUSujgAhUMJyUMb+SA@mail.gmail.com
Backpatch-through: 12
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/heap.c | 41 | ||||
-rw-r--r-- | src/backend/catalog/index.c | 3 |
2 files changed, 44 insertions, 0 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 67144aa3c94..9ccf378d45b 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -3142,6 +3142,47 @@ cookConstraint(ParseState *pstate, return expr; } +/* + * CopyStatistics --- copy entries in pg_statistic from one rel to another + */ +void +CopyStatistics(Oid fromrelid, Oid torelid) +{ + HeapTuple tup; + SysScanDesc scan; + ScanKeyData key[1]; + Relation statrel; + + statrel = table_open(StatisticRelationId, RowExclusiveLock); + + /* Now search for stat records */ + ScanKeyInit(&key[0], + Anum_pg_statistic_starelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(fromrelid)); + + scan = systable_beginscan(statrel, StatisticRelidAttnumInhIndexId, + true, NULL, 1, key); + + while (HeapTupleIsValid((tup = systable_getnext(scan)))) + { + Form_pg_statistic statform; + + /* make a modifiable copy */ + tup = heap_copytuple(tup); + statform = (Form_pg_statistic) GETSTRUCT(tup); + + /* update the copy of the tuple and insert it */ + statform->starelid = torelid; + CatalogTupleInsert(statrel, tup); + + heap_freetuple(tup); + } + + systable_endscan(scan); + + table_close(statrel, RowExclusiveLock); +} /* * RemoveStatistics --- remove entries in pg_statistic for a rel or column diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 0974f3e23a2..a18cc7cad30 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -1711,6 +1711,9 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName) } } + /* Copy data of pg_statistic from the old index to the new one */ + CopyStatistics(oldIndexId, newIndexId); + /* Close relations */ table_close(pg_class, RowExclusiveLock); table_close(pg_index, RowExclusiveLock); |