Keep stats up to date for partitioned tables
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Sat, 28 Aug 2021 19:58:23 +0000 (15:58 -0400)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Sat, 28 Aug 2021 19:58:23 +0000 (15:58 -0400)
In the long-going saga for analyze on partitioned tables, one thing I
missed while reverting 0827e8af70f4 is the maintenance of analyze count
and last analyze time for partitioned tables.  This is a mostly trivial
change that enables users assess the need for invoking manual ANALYZE on
partitioned tables.

This patch, posted by Justin and modified a bit by me (Álvaro), can be
mostly traced back to Hosoya-san, though any problems introduced with
the scissors are mine.

Backpatch to 14, in line with 6f8127b73901.

Co-authored-by: Yuzuko Hosoya <yuzukohosoya@gmail.com>
Co-authored-by: Justin Pryzby <pryzby@telsasoft.com>
Co-authored-by: Álvaro Herrera <alvherre@alvh.no-ip.org>
Reported-by: Justin Pryzby <pryzby@telsasoft.com>
Discussion: https://postgr.es/m/20210816222810.GE10479@telsasoft.com

src/backend/commands/analyze.c
src/backend/postmaster/pgstat.c

index 03cdf4f5e8e3e3e65fca8c6cc155e8e39731093c..8bfb2ad9584fdd71f0268b657d566074e3a751aa 100644 (file)
@@ -626,8 +626,8 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
                                 PROGRESS_ANALYZE_PHASE_FINALIZE_ANALYZE);
 
    /*
-    * Update pages/tuples stats in pg_class, and report ANALYZE to the stats
-    * collector ... but not if we're doing inherited stats.
+    * Update pages/tuples stats in pg_class ... 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,20 +668,33 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
                                InvalidMultiXactId,
                                in_outer_xact);
        }
-
+   }
+   else if (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.
+        * Partitioned tables don't have storage, so we don't set any fields
+        * in their pg_class entries except for reltuples 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)
        pgstat_report_analyze(onerel, totalrows, totaldeadrows,
                              (va_cols == NIL));
-   }
+   else if (onerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+       pgstat_report_analyze(onerel, 0, 0, (va_cols == NIL));
 
    /*
     * If this isn't part of VACUUM ANALYZE, let index AMs do cleanup.
index a3c35bdf6097a4dc3fd9276afb94bc36ad4f180d..4a280897b1907af2d08367fae3f693697efe4667 100644 (file)
@@ -1632,8 +1632,11 @@ pgstat_report_analyze(Relation rel,
     * be double-counted after commit.  (This approach also ensures that the
     * collector ends up with the right numbers if we abort instead of
     * committing.)
+    *
+    * Waste no time on partitioned tables, though.
     */
-   if (rel->pgstat_info != NULL)
+   if (rel->pgstat_info != NULL &&
+       rel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE)
    {
        PgStat_TableXactStatus *trans;
 
@@ -1997,8 +2000,10 @@ pgstat_initstats(Relation rel)
    Oid         rel_id = rel->rd_id;
    char        relkind = rel->rd_rel->relkind;
 
-   /* We only count stats for things that have storage */
-   if (!RELKIND_HAS_STORAGE(relkind))
+   /*
+    * We only count stats for relations with storage and partitioned tables
+    */
+   if (!RELKIND_HAS_STORAGE(relkind) && relkind != RELKIND_PARTITIONED_TABLE)
    {
        rel->pgstat_info = NULL;
        return;