aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/vacuumlazy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/vacuumlazy.c')
-rw-r--r--src/backend/commands/vacuumlazy.c86
1 files changed, 63 insertions, 23 deletions
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index 9ac84e8293a..f9da24c491f 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -114,9 +114,9 @@ typedef struct LVRelStats
BlockNumber pinskipped_pages; /* # of pages we skipped due to a pin */
BlockNumber frozenskipped_pages; /* # of frozen pages we skipped */
BlockNumber tupcount_pages; /* pages whose tuples we counted */
- double scanned_tuples; /* counts only tuples on tupcount_pages */
- double old_rel_tuples; /* previous value of pg_class.reltuples */
+ double old_live_tuples; /* previous value of pg_class.reltuples */
double new_rel_tuples; /* new estimated total # of tuples */
+ double new_live_tuples; /* new estimated total # of live tuples */
double new_dead_tuples; /* new estimated total # of dead tuples */
BlockNumber pages_removed;
double tuples_deleted;
@@ -196,7 +196,6 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
TransactionId xidFullScanLimit;
MultiXactId mxactFullScanLimit;
BlockNumber new_rel_pages;
- double new_rel_tuples;
BlockNumber new_rel_allvisible;
double new_live_tuples;
TransactionId new_frozen_xid;
@@ -245,7 +244,7 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
vacrelstats = (LVRelStats *) palloc0(sizeof(LVRelStats));
vacrelstats->old_rel_pages = onerel->rd_rel->relpages;
- vacrelstats->old_rel_tuples = onerel->rd_rel->reltuples;
+ vacrelstats->old_live_tuples = onerel->rd_rel->reltuples;
vacrelstats->num_index_scans = 0;
vacrelstats->pages_removed = 0;
vacrelstats->lock_waiter_detected = false;
@@ -311,11 +310,11 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
* since then we don't know for certain that all tuples have a newer xmin.
*/
new_rel_pages = vacrelstats->rel_pages;
- new_rel_tuples = vacrelstats->new_rel_tuples;
+ new_live_tuples = vacrelstats->new_live_tuples;
if (vacrelstats->tupcount_pages == 0 && new_rel_pages > 0)
{
new_rel_pages = vacrelstats->old_rel_pages;
- new_rel_tuples = vacrelstats->old_rel_tuples;
+ new_live_tuples = vacrelstats->old_live_tuples;
}
visibilitymap_count(onerel, &new_rel_allvisible, NULL);
@@ -327,7 +326,7 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
vac_update_relstats(onerel,
new_rel_pages,
- new_rel_tuples,
+ new_live_tuples,
new_rel_allvisible,
vacrelstats->hasindex,
new_frozen_xid,
@@ -335,10 +334,6 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params,
false);
/* report results to the stats collector, too */
- new_live_tuples = new_rel_tuples - vacrelstats->new_dead_tuples;
- if (new_live_tuples < 0)
- new_live_tuples = 0; /* just in case */
-
pgstat_report_vacuum(RelationGetRelid(onerel),
onerel->rd_rel->relisshared,
new_live_tuples,
@@ -471,10 +466,11 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
TransactionId relminmxid = onerel->rd_rel->relminmxid;
BlockNumber empty_pages,
vacuumed_pages;
- double num_tuples,
- tups_vacuumed,
- nkeep,
- nunused;
+ double num_tuples, /* total number of nonremovable tuples */
+ live_tuples, /* live tuples (reltuples estimate) */
+ tups_vacuumed, /* tuples cleaned up by vacuum */
+ nkeep, /* dead-but-not-removable tuples */
+ nunused; /* unused item pointers */
IndexBulkDeleteResult **indstats;
int i;
PGRUsage ru0;
@@ -505,7 +501,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
relname)));
empty_pages = vacuumed_pages = 0;
- num_tuples = tups_vacuumed = nkeep = nunused = 0;
+ num_tuples = live_tuples = tups_vacuumed = nkeep = nunused = 0;
indstats = (IndexBulkDeleteResult **)
palloc0(nindexes * sizeof(IndexBulkDeleteResult *));
@@ -988,6 +984,17 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
tupgone = false;
+ /*
+ * The criteria for counting a tuple as live in this block need to
+ * match what analyze.c's acquire_sample_rows() does, otherwise
+ * VACUUM and ANALYZE may produce wildly different reltuples
+ * values, e.g. when there are many recently-dead tuples.
+ *
+ * The logic here is a bit simpler than acquire_sample_rows(), as
+ * VACUUM can't run inside a transaction block, which makes some
+ * cases impossible (e.g. in-progress insert from the same
+ * transaction).
+ */
switch (HeapTupleSatisfiesVacuum(&tuple, OldestXmin, buf))
{
case HEAPTUPLE_DEAD:
@@ -1029,6 +1036,12 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
relname, blkno, offnum);
/*
+ * Count it as live. Not only is this natural, but it's
+ * also what acquire_sample_rows() does.
+ */
+ live_tuples += 1;
+
+ /*
* Is the tuple definitely visible to all transactions?
*
* NB: Like with per-tuple hint bits, we can't set the
@@ -1073,12 +1086,29 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
all_visible = false;
break;
case HEAPTUPLE_INSERT_IN_PROGRESS:
- /* This is an expected case during concurrent vacuum */
+
+ /*
+ * This is an expected case during concurrent vacuum.
+ *
+ * We do not count these rows as live, because we expect
+ * the inserting transaction to update the counters at
+ * commit, and we assume that will happen only after we
+ * report our results. This assumption is a bit shaky,
+ * but it is what acquire_sample_rows() does, so be
+ * consistent.
+ */
all_visible = false;
break;
case HEAPTUPLE_DELETE_IN_PROGRESS:
/* This is an expected case during concurrent vacuum */
all_visible = false;
+
+ /*
+ * Count such rows as live. As above, we assume the
+ * deleting transaction will commit and update the
+ * counters after we report.
+ */
+ live_tuples += 1;
break;
default:
elog(ERROR, "unexpected HeapTupleSatisfiesVacuum result");
@@ -1281,15 +1311,18 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats *vacrelstats,
pfree(frozen);
/* save stats for use later */
- vacrelstats->scanned_tuples = num_tuples;
vacrelstats->tuples_deleted = tups_vacuumed;
vacrelstats->new_dead_tuples = nkeep;
/* now we can compute the new value for pg_class.reltuples */
- vacrelstats->new_rel_tuples = vac_estimate_reltuples(onerel,
- nblocks,
- vacrelstats->tupcount_pages,
- num_tuples);
+ vacrelstats->new_live_tuples = vac_estimate_reltuples(onerel,
+ nblocks,
+ vacrelstats->tupcount_pages,
+ live_tuples);
+
+ /* also compute total number of surviving heap entries */
+ vacrelstats->new_rel_tuples =
+ vacrelstats->new_live_tuples + vacrelstats->new_dead_tuples;
/*
* Release any remaining pin on visibility map page.
@@ -1625,7 +1658,8 @@ lazy_vacuum_index(Relation indrel,
ivinfo.analyze_only = false;
ivinfo.estimated_count = true;
ivinfo.message_level = elevel;
- ivinfo.num_heap_tuples = vacrelstats->old_rel_tuples;
+ /* We can only provide an approximate value of num_heap_tuples here */
+ ivinfo.num_heap_tuples = vacrelstats->old_live_tuples;
ivinfo.strategy = vac_strategy;
/* Do bulk deletion */
@@ -1656,6 +1690,12 @@ lazy_cleanup_index(Relation indrel,
ivinfo.analyze_only = false;
ivinfo.estimated_count = (vacrelstats->tupcount_pages < vacrelstats->rel_pages);
ivinfo.message_level = elevel;
+
+ /*
+ * Now we can provide a better estimate of total number of surviving
+ * tuples (we assume indexes are more interested in that than in the
+ * number of nominally live tuples).
+ */
ivinfo.num_heap_tuples = vacrelstats->new_rel_tuples;
ivinfo.strategy = vac_strategy;