mirror of
https://github.com/postgres/postgres.git
synced 2025-11-04 20:11:56 +03:00
Revert analyze support for partitioned tables
This reverts the following commits:1b5617eb84Describe (auto-)analyze behavior for partitioned tables0e69f705ccSet pg_class.reltuples for partitioned tables41badeaba8Document ANALYZE storage parameters for partitioned tables0827e8af70autovacuum: handle analyze for partitioned tables There are efficiency issues in this code when handling databases with large numbers of partitions, and it doesn't look like there isn't any trivial way to handle those. There are some other issues as well. It's now too late in the cycle for nontrivial fixes, so we'll have to let Postgres 14 users continue to manually deal with ANALYZE their partitioned tables, and hopefully we can fix the issues for Postgres 15. I kept [most of]be280cdad2("Don't reset relhasindex for partitioned tables on ANALYZE") because while we added it due to0827e8af70, it is a good bugfix in its own right, since it affects manual analyze as well as autovacuum-induced analyze, and there's no reason to revert it. I retained the addition of relkind 'p' to tables included by pg_stat_user_tables, because reverting that would require a catversion bump. Also, in pg14 only, I keep a struct member that was added to PgStat_TabStatEntry to avoid breaking compatibility with existing stat files. Backpatch to 14. Discussion: https://postgr.es/m/20210722205458.f2bug3z6qzxzpx2s@alap3.anarazel.de
This commit is contained in:
@@ -626,8 +626,8 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
|
||||
PROGRESS_ANALYZE_PHASE_FINALIZE_ANALYZE);
|
||||
|
||||
/*
|
||||
* Update pages/tuples stats in pg_class ... but not if we're doing
|
||||
* inherited stats.
|
||||
* Update pages/tuples stats in pg_class, and report ANALYZE to the stats
|
||||
* collector ... but not if we're doing inherited stats.
|
||||
*
|
||||
* We assume that VACUUM hasn't set pg_class.reltuples already, even
|
||||
* during a VACUUM ANALYZE. Although VACUUM often updates pg_class,
|
||||
@@ -668,47 +668,19 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
|
||||
InvalidMultiXactId,
|
||||
in_outer_xact);
|
||||
}
|
||||
}
|
||||
else if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
|
||||
{
|
||||
/*
|
||||
* Partitioned tables don't have storage, so we don't set any fields
|
||||
* in their pg_class entries except for reltuples, which is necessary
|
||||
* for auto-analyze to work properly, and relhasindex.
|
||||
*/
|
||||
vac_update_relstats(onerel, -1, totalrows,
|
||||
0, hasindex, InvalidTransactionId,
|
||||
InvalidMultiXactId,
|
||||
in_outer_xact);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now report ANALYZE to the stats collector. For regular tables, we do
|
||||
* it only if not doing inherited stats. For partitioned tables, we only
|
||||
* do it for inherited stats. (We're never called for not-inherited stats
|
||||
* on partitioned tables anyway.)
|
||||
*
|
||||
* Reset the changes_since_analyze counter only if we analyzed all
|
||||
* columns; otherwise, there is still work for auto-analyze to do.
|
||||
*/
|
||||
if (!inh || onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
|
||||
/*
|
||||
* Now report ANALYZE to the stats collector.
|
||||
*
|
||||
* We deliberately don't report to the stats collector when doing
|
||||
* inherited stats, because the stats collector only tracks per-table
|
||||
* stats.
|
||||
*
|
||||
* Reset the changes_since_analyze counter only if we analyzed all
|
||||
* columns; otherwise, there is still work for auto-analyze to do.
|
||||
*/
|
||||
pgstat_report_analyze(onerel, totalrows, totaldeadrows,
|
||||
(va_cols == NIL));
|
||||
|
||||
/*
|
||||
* If this is a manual analyze of all columns of a permanent leaf
|
||||
* partition, and not doing inherited stats, also let the collector know
|
||||
* about the ancestor tables of this partition. Autovacuum does the
|
||||
* equivalent of this at the start of its run, so there's no reason to do
|
||||
* it there.
|
||||
*/
|
||||
if (!inh && !IsAutoVacuumWorkerProcess() &&
|
||||
(va_cols == NIL) &&
|
||||
onerel->rd_rel->relispartition &&
|
||||
onerel->rd_rel->relkind == RELKIND_RELATION &&
|
||||
onerel->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT)
|
||||
{
|
||||
pgstat_report_anl_ancestors(RelationGetRelid(onerel));
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -336,7 +336,6 @@ typedef struct ForeignTruncateInfo
|
||||
static void truncate_check_rel(Oid relid, Form_pg_class reltuple);
|
||||
static void truncate_check_perms(Oid relid, Form_pg_class reltuple);
|
||||
static void truncate_check_activity(Relation rel);
|
||||
static void truncate_update_partedrel_stats(List *parted_rels);
|
||||
static void RangeVarCallbackForTruncate(const RangeVar *relation,
|
||||
Oid relId, Oid oldRelId, void *arg);
|
||||
static List *MergeAttributes(List *schema, List *supers, char relpersistence,
|
||||
@@ -1740,7 +1739,6 @@ ExecuteTruncateGuts(List *explicit_rels,
|
||||
{
|
||||
List *rels;
|
||||
List *seq_relids = NIL;
|
||||
List *parted_rels = NIL;
|
||||
HTAB *ft_htab = NULL;
|
||||
EState *estate;
|
||||
ResultRelInfo *resultRelInfos;
|
||||
@@ -1889,15 +1887,9 @@ ExecuteTruncateGuts(List *explicit_rels,
|
||||
{
|
||||
Relation rel = (Relation) lfirst(cell);
|
||||
|
||||
/*
|
||||
* Save OID of partitioned tables for later; nothing else to do for
|
||||
* them here.
|
||||
*/
|
||||
/* Skip partitioned tables as there is nothing to do */
|
||||
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
|
||||
{
|
||||
parted_rels = lappend_oid(parted_rels, RelationGetRelid(rel));
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build the lists of foreign tables belonging to each foreign server
|
||||
@@ -2045,9 +2037,6 @@ ExecuteTruncateGuts(List *explicit_rels,
|
||||
ResetSequence(seq_relid);
|
||||
}
|
||||
|
||||
/* Reset partitioned tables' pg_class.reltuples */
|
||||
truncate_update_partedrel_stats(parted_rels);
|
||||
|
||||
/*
|
||||
* Write a WAL record to allow this set of actions to be logically
|
||||
* decoded.
|
||||
@@ -2194,40 +2183,6 @@ truncate_check_activity(Relation rel)
|
||||
CheckTableNotInUse(rel, "TRUNCATE");
|
||||
}
|
||||
|
||||
/*
|
||||
* Update pg_class.reltuples for all the given partitioned tables to 0.
|
||||
*/
|
||||
static void
|
||||
truncate_update_partedrel_stats(List *parted_rels)
|
||||
{
|
||||
Relation pg_class;
|
||||
ListCell *lc;
|
||||
|
||||
pg_class = table_open(RelationRelationId, RowExclusiveLock);
|
||||
|
||||
foreach(lc, parted_rels)
|
||||
{
|
||||
Oid relid = lfirst_oid(lc);
|
||||
HeapTuple tuple;
|
||||
Form_pg_class rd_rel;
|
||||
|
||||
tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
|
||||
if (!HeapTupleIsValid(tuple))
|
||||
elog(ERROR, "could not find tuple for relation %u", relid);
|
||||
rd_rel = (Form_pg_class) GETSTRUCT(tuple);
|
||||
if (rd_rel->reltuples != (float4) 0)
|
||||
{
|
||||
rd_rel->reltuples = (float4) 0;
|
||||
|
||||
heap_inplace_update(pg_class, tuple);
|
||||
}
|
||||
|
||||
heap_freetuple(tuple);
|
||||
}
|
||||
|
||||
table_close(pg_class, RowExclusiveLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* storage_name
|
||||
* returns the name corresponding to a typstorage/attstorage enum value
|
||||
|
||||
Reference in New Issue
Block a user