Skip to content

Commit 6f8127b

Browse files
committed
Revert analyze support for partitioned tables
This reverts the following commits: 1b5617e Describe (auto-)analyze behavior for partitioned tables 0e69f70 Set pg_class.reltuples for partitioned tables 41badea Document ANALYZE storage parameters for partitioned tables 0827e8a autovacuum: 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] be280cd ("Don't reset relhasindex for partitioned tables on ANALYZE") because while we added it due to 0827e8a, 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
1 parent 3aafc03 commit 6f8127b

File tree

11 files changed

+56
-320
lines changed

11 files changed

+56
-320
lines changed

doc/src/sgml/maintenance.sgml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -817,12 +817,6 @@ analyze threshold = analyze base threshold + analyze scale factor * number of tu
817817
</programlisting>
818818
is compared to the total number of tuples inserted, updated, or deleted
819819
since the last <command>ANALYZE</command>.
820-
For partitioned tables, inserts, updates and deletes on partitions
821-
are counted towards this threshold; however, DDL
822-
operations such as <literal>ATTACH</literal>, <literal>DETACH</literal>
823-
and <literal>DROP</literal> are not, so running a manual
824-
<command>ANALYZE</command> is recommended if the partition added or
825-
removed contains a statistically significant volume of data.
826820
</para>
827821

828822
<para>

doc/src/sgml/perform.sgml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,8 +1767,7 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse;
17671767
<para>
17681768
Whenever you have significantly altered the distribution of data
17691769
within a table, running <link linkend="sql-analyze"><command>ANALYZE</command></link> is strongly recommended. This
1770-
includes bulk loading large amounts of data into the table as well as
1771-
attaching, detaching or dropping partitions. Running
1770+
includes bulk loading large amounts of data into the table. Running
17721771
<command>ANALYZE</command> (or <command>VACUUM ANALYZE</command>)
17731772
ensures that the planner has up-to-date statistics about the
17741773
table. With no statistics or obsolete statistics, the planner might

doc/src/sgml/ref/analyze.sgml

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -250,38 +250,20 @@ ANALYZE [ VERBOSE ] [ <replaceable class="parameter">table_and_columns</replacea
250250
</para>
251251

252252
<para>
253-
If the table being analyzed is partitioned, <command>ANALYZE</command>
254-
will gather statistics by sampling blocks randomly from its partitions;
255-
in addition, it will recurse into each partition and update its statistics.
256-
(However, in multi-level partitioning scenarios, each leaf partition
257-
will only be analyzed once.)
258-
By contrast, if the table being analyzed has inheritance children,
259-
<command>ANALYZE</command> will gather statistics for it twice:
260-
once on the rows of the parent table only, and a second time on the
261-
rows of the parent table with all of its children. This second set of
262-
statistics is needed when planning queries that traverse the entire
263-
inheritance tree. The child tables themselves are not individually
264-
analyzed in this case.
253+
If the table being analyzed has one or more children,
254+
<command>ANALYZE</command> will gather statistics twice: once on the
255+
rows of the parent table only, and a second time on the rows of the
256+
parent table with all of its children. This second set of statistics
257+
is needed when planning queries that traverse the entire inheritance
258+
tree. The autovacuum daemon, however, will only consider inserts or
259+
updates on the parent table itself when deciding whether to trigger an
260+
automatic analyze for that table. If that table is rarely inserted into
261+
or updated, the inheritance statistics will not be up to date unless you
262+
run <command>ANALYZE</command> manually.
265263
</para>
266264

267265
<para>
268-
The autovacuum daemon counts inserts, updates and deletes in the
269-
partitions to determine if auto-analyze is needed. However, adding
270-
or removing partitions does not affect autovacuum daemon decisions,
271-
so triggering a manual <command>ANALYZE</command> is recommended
272-
when this occurs.
273-
</para>
274-
275-
<para>
276-
Tuples changed in inheritance children do not count towards analyze
277-
on the parent table. If the parent table is empty or rarely modified,
278-
it may never be processed by autovacuum. It's necessary to
279-
periodically run a manual <command>ANALYZE</command> to keep the
280-
statistics of the table hierarchy up to date.
281-
</para>
282-
283-
<para>
284-
If any of the child tables or partitions are foreign tables whose foreign data wrappers
266+
If any of the child tables are foreign tables whose foreign data wrappers
285267
do not support <command>ANALYZE</command>, those child tables are ignored while
286268
gathering inheritance statistics.
287269
</para>

doc/src/sgml/ref/create_table.sgml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,8 +1374,8 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
13741374
If a table parameter value is set and the
13751375
equivalent <literal>toast.</literal> parameter is not, the TOAST table
13761376
will use the table's parameter value.
1377-
Except where noted, these parameters are not supported on partitioned
1378-
tables; however, you can specify them on individual leaf partitions.
1377+
Specifying these parameters for partitioned tables is not supported,
1378+
but you may specify them for individual leaf partitions.
13791379
</para>
13801380

13811381
<variablelist>
@@ -1457,8 +1457,6 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
14571457
If true, the autovacuum daemon will perform automatic <command>VACUUM</command>
14581458
and/or <command>ANALYZE</command> operations on this table following the rules
14591459
discussed in <xref linkend="autovacuum"/>.
1460-
This parameter can be set for partitioned tables to prevent autovacuum
1461-
from running <command>ANALYZE</command> on them.
14621460
If false, this table will not be autovacuumed, except to prevent
14631461
transaction ID wraparound. See <xref linkend="vacuum-for-wraparound"/> for
14641462
more about wraparound prevention.
@@ -1590,7 +1588,6 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
15901588
<para>
15911589
Per-table value for <xref linkend="guc-autovacuum-analyze-threshold"/>
15921590
parameter.
1593-
This parameter can be set for partitioned tables.
15941591
</para>
15951592
</listitem>
15961593
</varlistentry>
@@ -1606,7 +1603,6 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
16061603
<para>
16071604
Per-table value for <xref linkend="guc-autovacuum-analyze-scale-factor"/>
16081605
parameter.
1609-
This parameter can be set for partitioned tables.
16101606
</para>
16111607
</listitem>
16121608
</varlistentry>

doc/src/sgml/ref/pg_restore.sgml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -922,10 +922,8 @@ CREATE DATABASE foo WITH TEMPLATE template0;
922922

923923
<para>
924924
Once restored, it is wise to run <command>ANALYZE</command> on each
925-
restored table so the optimizer has useful statistics.
926-
If the table is a partition or an inheritance child, it may also be useful
927-
to analyze the parent to update statistics for the table hierarchy.
928-
See <xref linkend="vacuum-for-statistics"/> and
925+
restored table so the optimizer has useful statistics; see
926+
<xref linkend="vacuum-for-statistics"/> and
929927
<xref linkend="autovacuum"/> for more information.
930928
</para>
931929

src/backend/access/common/reloptions.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static relopt_bool boolRelOpts[] =
108108
{
109109
"autovacuum_enabled",
110110
"Enables autovacuum in this relation",
111-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST | RELOPT_KIND_PARTITIONED,
111+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
112112
ShareUpdateExclusiveLock
113113
},
114114
true
@@ -237,7 +237,7 @@ static relopt_int intRelOpts[] =
237237
{
238238
"autovacuum_analyze_threshold",
239239
"Minimum number of tuple inserts, updates or deletes prior to analyze",
240-
RELOPT_KIND_HEAP | RELOPT_KIND_PARTITIONED,
240+
RELOPT_KIND_HEAP,
241241
ShareUpdateExclusiveLock
242242
},
243243
-1, 0, INT_MAX
@@ -411,7 +411,7 @@ static relopt_real realRelOpts[] =
411411
{
412412
"autovacuum_analyze_scale_factor",
413413
"Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
414-
RELOPT_KIND_HEAP | RELOPT_KIND_PARTITIONED,
414+
RELOPT_KIND_HEAP,
415415
ShareUpdateExclusiveLock
416416
},
417417
-1, 0.0, 100.0
@@ -1979,11 +1979,12 @@ bytea *
19791979
partitioned_table_reloptions(Datum reloptions, bool validate)
19801980
{
19811981
/*
1982-
* autovacuum_enabled, autovacuum_analyze_threshold and
1983-
* autovacuum_analyze_scale_factor are supported for partitioned tables.
1982+
* There are no options for partitioned tables yet, but this is able to do
1983+
* some validation.
19841984
*/
1985-
1986-
return default_reloptions(reloptions, validate, RELOPT_KIND_PARTITIONED);
1985+
return (bytea *) build_reloptions(reloptions, validate,
1986+
RELOPT_KIND_PARTITIONED,
1987+
0, NULL, 0);
19871988
}
19881989

19891990
/*

src/backend/commands/analyze.c

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -626,8 +626,8 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
626626
PROGRESS_ANALYZE_PHASE_FINALIZE_ANALYZE);
627627

628628
/*
629-
* Update pages/tuples stats in pg_class ... but not if we're doing
630-
* inherited stats.
629+
* Update pages/tuples stats in pg_class, and report ANALYZE to the stats
630+
* collector ... but not if we're doing inherited stats.
631631
*
632632
* We assume that VACUUM hasn't set pg_class.reltuples already, even
633633
* during a VACUUM ANALYZE. Although VACUUM often updates pg_class,
@@ -668,47 +668,19 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
668668
InvalidMultiXactId,
669669
in_outer_xact);
670670
}
671-
}
672-
else if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
673-
{
671+
674672
/*
675-
* Partitioned tables don't have storage, so we don't set any fields
676-
* in their pg_class entries except for reltuples, which is necessary
677-
* for auto-analyze to work properly, and relhasindex.
673+
* Now report ANALYZE to the stats collector.
674+
*
675+
* We deliberately don't report to the stats collector when doing
676+
* inherited stats, because the stats collector only tracks per-table
677+
* stats.
678+
*
679+
* Reset the changes_since_analyze counter only if we analyzed all
680+
* columns; otherwise, there is still work for auto-analyze to do.
678681
*/
679-
vac_update_relstats(onerel, -1, totalrows,
680-
0, hasindex, InvalidTransactionId,
681-
InvalidMultiXactId,
682-
in_outer_xact);
683-
}
684-
685-
/*
686-
* Now report ANALYZE to the stats collector. For regular tables, we do
687-
* it only if not doing inherited stats. For partitioned tables, we only
688-
* do it for inherited stats. (We're never called for not-inherited stats
689-
* on partitioned tables anyway.)
690-
*
691-
* Reset the changes_since_analyze counter only if we analyzed all
692-
* columns; otherwise, there is still work for auto-analyze to do.
693-
*/
694-
if (!inh || onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
695682
pgstat_report_analyze(onerel, totalrows, totaldeadrows,
696683
(va_cols == NIL));
697-
698-
/*
699-
* If this is a manual analyze of all columns of a permanent leaf
700-
* partition, and not doing inherited stats, also let the collector know
701-
* about the ancestor tables of this partition. Autovacuum does the
702-
* equivalent of this at the start of its run, so there's no reason to do
703-
* it there.
704-
*/
705-
if (!inh && !IsAutoVacuumWorkerProcess() &&
706-
(va_cols == NIL) &&
707-
onerel->rd_rel->relispartition &&
708-
onerel->rd_rel->relkind == RELKIND_RELATION &&
709-
onerel->rd_rel->relpersistence == RELPERSISTENCE_PERMANENT)
710-
{
711-
pgstat_report_anl_ancestors(RelationGetRelid(onerel));
712684
}
713685

714686
/*

src/backend/commands/tablecmds.c

Lines changed: 1 addition & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,6 @@ typedef struct ForeignTruncateInfo
336336
static void truncate_check_rel(Oid relid, Form_pg_class reltuple);
337337
static void truncate_check_perms(Oid relid, Form_pg_class reltuple);
338338
static void truncate_check_activity(Relation rel);
339-
static void truncate_update_partedrel_stats(List *parted_rels);
340339
static void RangeVarCallbackForTruncate(const RangeVar *relation,
341340
Oid relId, Oid oldRelId, void *arg);
342341
static List *MergeAttributes(List *schema, List *supers, char relpersistence,
@@ -1740,7 +1739,6 @@ ExecuteTruncateGuts(List *explicit_rels,
17401739
{
17411740
List *rels;
17421741
List *seq_relids = NIL;
1743-
List *parted_rels = NIL;
17441742
HTAB *ft_htab = NULL;
17451743
EState *estate;
17461744
ResultRelInfo *resultRelInfos;
@@ -1889,15 +1887,9 @@ ExecuteTruncateGuts(List *explicit_rels,
18891887
{
18901888
Relation rel = (Relation) lfirst(cell);
18911889

1892-
/*
1893-
* Save OID of partitioned tables for later; nothing else to do for
1894-
* them here.
1895-
*/
1890+
/* Skip partitioned tables as there is nothing to do */
18961891
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
1897-
{
1898-
parted_rels = lappend_oid(parted_rels, RelationGetRelid(rel));
18991892
continue;
1900-
}
19011893

19021894
/*
19031895
* Build the lists of foreign tables belonging to each foreign server
@@ -2045,9 +2037,6 @@ ExecuteTruncateGuts(List *explicit_rels,
20452037
ResetSequence(seq_relid);
20462038
}
20472039

2048-
/* Reset partitioned tables' pg_class.reltuples */
2049-
truncate_update_partedrel_stats(parted_rels);
2050-
20512040
/*
20522041
* Write a WAL record to allow this set of actions to be logically
20532042
* decoded.
@@ -2194,40 +2183,6 @@ truncate_check_activity(Relation rel)
21942183
CheckTableNotInUse(rel, "TRUNCATE");
21952184
}
21962185

2197-
/*
2198-
* Update pg_class.reltuples for all the given partitioned tables to 0.
2199-
*/
2200-
static void
2201-
truncate_update_partedrel_stats(List *parted_rels)
2202-
{
2203-
Relation pg_class;
2204-
ListCell *lc;
2205-
2206-
pg_class = table_open(RelationRelationId, RowExclusiveLock);
2207-
2208-
foreach(lc, parted_rels)
2209-
{
2210-
Oid relid = lfirst_oid(lc);
2211-
HeapTuple tuple;
2212-
Form_pg_class rd_rel;
2213-
2214-
tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relid));
2215-
if (!HeapTupleIsValid(tuple))
2216-
elog(ERROR, "could not find tuple for relation %u", relid);
2217-
rd_rel = (Form_pg_class) GETSTRUCT(tuple);
2218-
if (rd_rel->reltuples != (float4) 0)
2219-
{
2220-
rd_rel->reltuples = (float4) 0;
2221-
2222-
heap_inplace_update(pg_class, tuple);
2223-
}
2224-
2225-
heap_freetuple(tuple);
2226-
}
2227-
2228-
table_close(pg_class, RowExclusiveLock);
2229-
}
2230-
22312186
/*
22322187
* storage_name
22332188
* returns the name corresponding to a typstorage/attstorage enum value

0 commit comments

Comments
 (0)