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 commite57345975c
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 commit9f3665fb
, which dealt with issues in btvacuumcleanup(). Technically this fixes an unrelated issue, though. btvacuumcleanup() no longer provides an accurate num_index_tuples value following commit9f3665fb
(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 commit9f3665fb
.
This commit is contained in:
parent
9f3665fbfc
commit
5f8727f5a6
|
@ -1738,7 +1738,8 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
|
|||
end_parallel_vacuum(indstats, lps, nindexes);
|
||||
|
||||
/* Update index statistics */
|
||||
update_index_statistics(Irel, indstats, nindexes);
|
||||
if (vacrelstats->useindex)
|
||||
update_index_statistics(Irel, indstats, nindexes);
|
||||
|
||||
/* If no indexes, make log report that lazy_vacuum_heap would've made */
|
||||
if (vacuumed_pages)
|
||||
|
|
|
@ -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…
Reference in New Issue