mirror of
https://github.com/postgres/postgres.git
synced 2025-04-21 12:05:57 +03:00
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 e57345975cf 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 9f3665fb, 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 9f3665fb (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 9f3665fb.
This commit is contained in:
parent
9f3665fbfc
commit
5f8727f5a6
@ -1738,6 +1738,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
|
||||
end_parallel_vacuum(indstats, lps, nindexes);
|
||||
|
||||
/* Update index statistics */
|
||||
if (vacrelstats->useindex)
|
||||
update_index_statistics(Irel, indstats, nindexes);
|
||||
|
||||
/* If no indexes, make log report that lazy_vacuum_heap would've made */
|
||||
|
@ -600,8 +600,16 @@ 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,
|
||||
* exceptions exists. A "VACUUM (ANALYZE, INDEX_CLEANUP OFF)" command
|
||||
* will never update pg_class entries for index relations. It's also
|
||||
* possible that an individual index's pg_class entry won't be updated
|
||||
* during VACUUM if the index AM returns NULL from its amvacuumcleanup()
|
||||
* routine.
|
||||
*/
|
||||
if (!inh)
|
||||
{
|
||||
@ -609,6 +617,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
|
||||
|
||||
visibilitymap_count(onerel, &relallvisible, NULL);
|
||||
|
||||
/* Update pg_class for table relation */
|
||||
vac_update_relstats(onerel,
|
||||
relpages,
|
||||
totalrows,
|
||||
@ -617,15 +626,8 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
|
||||
InvalidTransactionId,
|
||||
InvalidMultiXactId,
|
||||
in_outer_xact);
|
||||
}
|
||||
|
||||
/*
|
||||
* Same for indexes. Vacuum always scans all indexes, so if we're part of
|
||||
* VACUUM ANALYZE, don't overwrite the accurate count already inserted by
|
||||
* VACUUM.
|
||||
*/
|
||||
if (!inh && !(params->options & VACOPT_VACUUM))
|
||||
{
|
||||
/* Same for indexes */
|
||||
for (ind = 0; ind < nindexes; ind++)
|
||||
{
|
||||
AnlIndexData *thisdata = &indexdata[ind];
|
||||
@ -641,20 +643,28 @@ do_analyze_rel(Relation onerel, VacuumParams *params,
|
||||
InvalidMultiXactId,
|
||||
in_outer_xact);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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));
|
||||
}
|
||||
|
||||
/*
|
||||
* Report ANALYZE to the stats collector, too. However, if doing
|
||||
* inherited stats we shouldn't report, 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.
|
||||
* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup.
|
||||
*
|
||||
* Note that most index AMs perform a no-op as a matter of policy for
|
||||
* amvacuumcleanup() when called in ANALYZE-only mode. The only exception
|
||||
* among core index AMs is GIN/ginvacuumcleanup().
|
||||
*/
|
||||
if (!inh)
|
||||
pgstat_report_analyze(onerel, totalrows, totaldeadrows,
|
||||
(va_cols == NIL));
|
||||
|
||||
/* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
|
||||
if (!(params->options & VACOPT_VACUUM))
|
||||
{
|
||||
for (ind = 0; ind < nindexes; ind++)
|
||||
|
Loading…
x
Reference in New Issue
Block a user