mirror of
https://github.com/postgres/postgres.git
synced 2025-07-09 22:41:56 +03:00
Don't reset relhasindex for partitioned tables on ANALYZE
Commit 0e69f705cc
introduced code to analyze partitioned table;
however, that code fails to preserve pg_class.relhasindex correctly.
Fix by observing whether any indexes exist rather than accidentally
falling through to assuming none do.
Backpatch to 14.
Author: Alexander Pyhalov <a.pyhalov@postgrespro.ru>
Reviewed-by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Reviewed-by: Zhihong Yu <zyu@yugabyte.com>
Discussion: https://postgr.es/m/CALNJ-vS1R3Qoe5t4tbzxrkpBtzRbPq1dDcW4RmA_a+oqweF30w@mail.gmail.com
This commit is contained in:
@ -420,20 +420,34 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
|
|||||||
/*
|
/*
|
||||||
* Open all indexes of the relation, and see if there are any analyzable
|
* Open all indexes of the relation, and see if there are any analyzable
|
||||||
* columns in the indexes. We do not analyze index columns if there was
|
* columns in the indexes. We do not analyze index columns if there was
|
||||||
* an explicit column list in the ANALYZE command, however. If we are
|
* an explicit column list in the ANALYZE command, however.
|
||||||
* doing a recursive scan, we don't want to touch the parent's indexes at
|
*
|
||||||
* all.
|
* If we are doing a recursive scan, we don't want to touch the parent's
|
||||||
|
* indexes at all. If we're processing a partitioned table, we need to
|
||||||
|
* know if there are any indexes, but we don't want to process them.
|
||||||
*/
|
*/
|
||||||
if (!inh)
|
if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
|
||||||
|
{
|
||||||
|
List *idxs = RelationGetIndexList(onerel);
|
||||||
|
|
||||||
|
Irel = NULL;
|
||||||
|
nindexes = 0;
|
||||||
|
hasindex = idxs != NIL;
|
||||||
|
list_free(idxs);
|
||||||
|
}
|
||||||
|
else if (!inh)
|
||||||
|
{
|
||||||
vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel);
|
vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel);
|
||||||
|
hasindex = nindexes > 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Irel = NULL;
|
Irel = NULL;
|
||||||
nindexes = 0;
|
nindexes = 0;
|
||||||
|
hasindex = false;
|
||||||
}
|
}
|
||||||
hasindex = (nindexes > 0);
|
|
||||||
indexdata = NULL;
|
indexdata = NULL;
|
||||||
if (hasindex)
|
if (nindexes > 0)
|
||||||
{
|
{
|
||||||
indexdata = (AnlIndexData *) palloc0(nindexes * sizeof(AnlIndexData));
|
indexdata = (AnlIndexData *) palloc0(nindexes * sizeof(AnlIndexData));
|
||||||
for (ind = 0; ind < nindexes; ind++)
|
for (ind = 0; ind < nindexes; ind++)
|
||||||
@ -572,7 +586,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
|
|||||||
MemoryContextResetAndDeleteChildren(col_context);
|
MemoryContextResetAndDeleteChildren(col_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasindex)
|
if (nindexes > 0)
|
||||||
compute_index_stats(onerel, totalrows,
|
compute_index_stats(onerel, totalrows,
|
||||||
indexdata, nindexes,
|
indexdata, nindexes,
|
||||||
rows, numrows,
|
rows, numrows,
|
||||||
@ -660,10 +674,10 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
|
|||||||
/*
|
/*
|
||||||
* Partitioned tables don't have storage, so we don't set any fields
|
* Partitioned tables don't have storage, so we don't set any fields
|
||||||
* in their pg_class entries except for reltuples, which is necessary
|
* in their pg_class entries except for reltuples, which is necessary
|
||||||
* for auto-analyze to work properly.
|
* for auto-analyze to work properly, and relhasindex.
|
||||||
*/
|
*/
|
||||||
vac_update_relstats(onerel, -1, totalrows,
|
vac_update_relstats(onerel, -1, totalrows,
|
||||||
0, false, InvalidTransactionId,
|
0, hasindex, InvalidTransactionId,
|
||||||
InvalidMultiXactId,
|
InvalidMultiXactId,
|
||||||
in_outer_xact);
|
in_outer_xact);
|
||||||
}
|
}
|
||||||
|
@ -199,6 +199,28 @@ VACUUM ANALYZE vacparted(a,b,a);
|
|||||||
ERROR: column "a" of relation "vacparted" appears more than once
|
ERROR: column "a" of relation "vacparted" appears more than once
|
||||||
ANALYZE vacparted(a,b,b);
|
ANALYZE vacparted(a,b,b);
|
||||||
ERROR: column "b" of relation "vacparted" appears more than once
|
ERROR: column "b" of relation "vacparted" appears more than once
|
||||||
|
-- partitioned table with index
|
||||||
|
CREATE TABLE vacparted_i (a int primary key, b varchar(100))
|
||||||
|
PARTITION BY HASH (a);
|
||||||
|
CREATE TABLE vacparted_i1 PARTITION OF vacparted_i
|
||||||
|
FOR VALUES WITH (MODULUS 2, REMAINDER 0);
|
||||||
|
CREATE TABLE vacparted_i2 PARTITION OF vacparted_i
|
||||||
|
FOR VALUES WITH (MODULUS 2, REMAINDER 1);
|
||||||
|
INSERT INTO vacparted_i SELECT i, 'test_'|| i from generate_series(1,10) i;
|
||||||
|
VACUUM (ANALYZE) vacparted_i;
|
||||||
|
VACUUM (FULL) vacparted_i;
|
||||||
|
VACUUM (FREEZE) vacparted_i;
|
||||||
|
SELECT relname, relhasindex FROM pg_class
|
||||||
|
WHERE relname LIKE 'vacparted_i%' AND relkind IN ('p','r')
|
||||||
|
ORDER BY relname;
|
||||||
|
relname | relhasindex
|
||||||
|
--------------+-------------
|
||||||
|
vacparted_i | t
|
||||||
|
vacparted_i1 | t
|
||||||
|
vacparted_i2 | t
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
DROP TABLE vacparted_i;
|
||||||
-- multiple tables specified
|
-- multiple tables specified
|
||||||
VACUUM vaccluster, vactst;
|
VACUUM vaccluster, vactst;
|
||||||
VACUUM vacparted, does_not_exist;
|
VACUUM vacparted, does_not_exist;
|
||||||
|
@ -170,6 +170,22 @@ VACUUM (FREEZE) vacparted;
|
|||||||
VACUUM ANALYZE vacparted(a,b,a);
|
VACUUM ANALYZE vacparted(a,b,a);
|
||||||
ANALYZE vacparted(a,b,b);
|
ANALYZE vacparted(a,b,b);
|
||||||
|
|
||||||
|
-- partitioned table with index
|
||||||
|
CREATE TABLE vacparted_i (a int primary key, b varchar(100))
|
||||||
|
PARTITION BY HASH (a);
|
||||||
|
CREATE TABLE vacparted_i1 PARTITION OF vacparted_i
|
||||||
|
FOR VALUES WITH (MODULUS 2, REMAINDER 0);
|
||||||
|
CREATE TABLE vacparted_i2 PARTITION OF vacparted_i
|
||||||
|
FOR VALUES WITH (MODULUS 2, REMAINDER 1);
|
||||||
|
INSERT INTO vacparted_i SELECT i, 'test_'|| i from generate_series(1,10) i;
|
||||||
|
VACUUM (ANALYZE) vacparted_i;
|
||||||
|
VACUUM (FULL) vacparted_i;
|
||||||
|
VACUUM (FREEZE) vacparted_i;
|
||||||
|
SELECT relname, relhasindex FROM pg_class
|
||||||
|
WHERE relname LIKE 'vacparted_i%' AND relkind IN ('p','r')
|
||||||
|
ORDER BY relname;
|
||||||
|
DROP TABLE vacparted_i;
|
||||||
|
|
||||||
-- multiple tables specified
|
-- multiple tables specified
|
||||||
VACUUM vaccluster, vactst;
|
VACUUM vaccluster, vactst;
|
||||||
VACUUM vacparted, does_not_exist;
|
VACUUM vacparted, does_not_exist;
|
||||||
|
Reference in New Issue
Block a user