diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 82061247988..84c23aa4c3f 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -3114,8 +3114,10 @@ relation_needs_vacanalyze(Oid relid, int effective_mxid_failsafe_age; float4 pcnt_unfrozen = 1; + float4 pcnt_allvisible = 1; float4 reltuples = classForm->reltuples; int32 relpages = classForm->relpages; + int32 relallvisible = classForm->relallvisible; int32 relallfrozen = classForm->relallfrozen; Assert(classForm != NULL); @@ -3259,6 +3261,24 @@ relation_needs_vacanalyze(Oid relid, if (reltuples < 0) reltuples = 0; + /* + * If we have data for relallvisible, calculate the all-visible + * percentage of the table to modify the vacuum scale factor. This makes + * the normal dead-tuple vacuum threshold more sensitive as fewer pages + * remain all-visible, without mixing pg_class.reltuples with the + * cumulative stats system's live tuple estimate. + */ + if (relpages > 0 && relallvisible > 0) + { + /* + * It could be the stats were updated manually and relallvisible > + * relpages. Clamp relallvisible to relpages to avoid nonsensical + * calculations. + */ + relallvisible = Min(relallvisible, relpages); + pcnt_allvisible = (float4) relallvisible / relpages; + } + /* * If we have data for relallfrozen, calculate the unfrozen percentage of * the table to modify insert scale factor. This helps us decide whether @@ -3276,13 +3296,15 @@ relation_needs_vacanalyze(Oid relid, pcnt_unfrozen = 1 - ((float4) relallfrozen / relpages); } - vacthresh = (float4) vac_base_thresh + vac_scale_factor * reltuples; + vacthresh = (float4) vac_base_thresh + + vac_scale_factor * reltuples * pcnt_allvisible; if (vac_max_thresh >= 0 && vacthresh > (float4) vac_max_thresh) vacthresh = (float4) vac_max_thresh; vacinsthresh = (float4) vac_ins_base_thresh + vac_ins_scale_factor * reltuples * pcnt_unfrozen; - anlthresh = (float4) anl_base_thresh + anl_scale_factor * reltuples; + anlthresh = (float4) anl_base_thresh + + anl_scale_factor * reltuples * pcnt_allvisible; /* Determine if this table needs vacuum, and update the score. */ scores->vac = (double) vactuples / Max(vacthresh, 1);