Skip to content

Commit 5f8727f

Browse files
VACUUM ANALYZE: Always update pg_class.reltuples.
vacuumlazy.c sometimes fails to update pg_class entries for each index (to ensure that pg_class.reltuples is current), even though analyze.c assumed that that must have happened during VACUUM ANALYZE. There are at least a couple of reasons for this. For example, vacuumlazy.c could fail to update pg_class when the index AM indicated that its statistics are merely an estimate, per the contract for amvacuumcleanup() routines established by commit e573459 back in 2006. Stop assuming that pg_class must have been updated with accurate statistics within VACUUM ANALYZE -- update pg_class for indexes at the same time as the table relation in all cases. That way VACUUM ANALYZE will never fail to keep pg_class.reltuples reasonably accurate. The only downside of this approach (compared to the old approach) is that it might inaccurately set pg_class.reltuples for indexes whose heap relation ends up with the same inaccurate value anyway. This doesn't seem too bad. We already consistently called vac_update_relstats() (to update pg_class) for the heap/table relation twice during any VACUUM ANALYZE -- once in vacuumlazy.c, and once in analyze.c. We now make sure that we call vac_update_relstats() at least once (though often twice) for each index. This is follow up work to commit 9f3665f, which dealt with issues in btvacuumcleanup(). Technically this fixes an unrelated issue, though. btvacuumcleanup() no longer provides an accurate num_index_tuples value following commit 9f3665f (when there was no btbulkdelete() call during the VACUUM operation in question), but hashvacuumcleanup() has worked in the same way for many years now. Author: Peter Geoghegan <pg@bowt.ie> Reviewed-By: Masahiko Sawada <sawada.mshk@gmail.com> Discussion: https://postgr.es/m/CAH2-WzknxdComjhqo4SUxVFk_Q1171GJO2ZgHZ1Y6pion6u8rA@mail.gmail.com Backpatch: 13-, just like commit 9f3665f.
1 parent 9f3665f commit 5f8727f

File tree

2 files changed

+32
-21
lines changed

2 files changed

+32
-21
lines changed

src/backend/access/heap/vacuumlazy.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1738,7 +1738,8 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
17381738
end_parallel_vacuum(indstats, lps, nindexes);
17391739

17401740
/* Update index statistics */
1741-
update_index_statistics(Irel, indstats, nindexes);
1741+
if (vacrelstats->useindex)
1742+
update_index_statistics(Irel, indstats, nindexes);
17421743

17431744
/* If no indexes, make log report that lazy_vacuum_heap would've made */
17441745
if (vacuumed_pages)

src/backend/commands/analyze.c

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -600,15 +600,24 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
600600
PROGRESS_ANALYZE_PHASE_FINALIZE_ANALYZE);
601601

602602
/*
603-
* Update pages/tuples stats in pg_class ... but not if we're doing
604-
* inherited stats.
603+
* Update pages/tuples stats in pg_class, and report ANALYZE to the stats
604+
* collector ... but not if we're doing inherited stats.
605+
*
606+
* We assume that VACUUM hasn't set pg_class.reltuples already, even
607+
* during a VACUUM ANALYZE. Although VACUUM often updates pg_class,
608+
* exceptions exists. A "VACUUM (ANALYZE, INDEX_CLEANUP OFF)" command
609+
* will never update pg_class entries for index relations. It's also
610+
* possible that an individual index's pg_class entry won't be updated
611+
* during VACUUM if the index AM returns NULL from its amvacuumcleanup()
612+
* routine.
605613
*/
606614
if (!inh)
607615
{
608616
BlockNumber relallvisible;
609617

610618
visibilitymap_count(onerel, &relallvisible, NULL);
611619

620+
/* Update pg_class for table relation */
612621
vac_update_relstats(onerel,
613622
relpages,
614623
totalrows,
@@ -617,15 +626,8 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
617626
InvalidTransactionId,
618627
InvalidMultiXactId,
619628
in_outer_xact);
620-
}
621629

622-
/*
623-
* Same for indexes. Vacuum always scans all indexes, so if we're part of
624-
* VACUUM ANALYZE, don't overwrite the accurate count already inserted by
625-
* VACUUM.
626-
*/
627-
if (!inh && !(params->options & VACOPT_VACUUM))
628-
{
630+
/* Same for indexes */
629631
for (ind = 0; ind < nindexes; ind++)
630632
{
631633
AnlIndexData *thisdata = &indexdata[ind];
@@ -641,20 +643,28 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
641643
InvalidMultiXactId,
642644
in_outer_xact);
643645
}
644-
}
645646

646-
/*
647-
* Report ANALYZE to the stats collector, too. However, if doing
648-
* inherited stats we shouldn't report, because the stats collector only
649-
* tracks per-table stats. Reset the changes_since_analyze counter only
650-
* if we analyzed all columns; otherwise, there is still work for
651-
* auto-analyze to do.
652-
*/
653-
if (!inh)
647+
/*
648+
* Now report ANALYZE to the stats collector.
649+
*
650+
* We deliberately don't report to the stats collector when doing
651+
* inherited stats, because the stats collector only tracks per-table
652+
* stats.
653+
*
654+
* Reset the changes_since_analyze counter only if we analyzed all
655+
* columns; otherwise, there is still work for auto-analyze to do.
656+
*/
654657
pgstat_report_analyze(onerel, totalrows, totaldeadrows,
655658
(va_cols == NIL));
659+
}
656660

657-
/* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
661+
/*
662+
* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup.
663+
*
664+
* Note that most index AMs perform a no-op as a matter of policy for
665+
* amvacuumcleanup() when called in ANALYZE-only mode. The only exception
666+
* among core index AMs is GIN/ginvacuumcleanup().
667+
*/
658668
if (!(params->options & VACOPT_VACUUM))
659669
{
660670
for (ind = 0; ind < nindexes; ind++)

0 commit comments

Comments
 (0)