Skip to content

Commit dd69597

Browse files
committed
Fix some problems with VACUUM (INDEX_CLEANUP FALSE).
The new nleft_dead_tuples and nleft_dead_itemids fields are confusing and do not seem like the correct way forward. One of them is tested via an assertion that can fail, as it has already done on buildfarm member topminnow. Remove the assertion and the fields. Change the logic for the case where a tuple is not initially pruned by heap_page_prune but later diagnosed HEAPTUPLE_DEAD by HeapTupleSatisfiesVacuum. Previously, tupgone = true was set in that case, which leads to treating the tuple as one that will be removed. In a normal vacuum, that's OK, because we'll remove index entries for it and then the second heap pass will remove the tuple itself, but when index cleanup is disabled, those things don't happen, so we must instead treat it as a recently-dead tuple that we have voluntarily chosen to keep. Report and analysis by Tom Lane. This patch loosely based on one from Masahiko Sawada, but I changed most of it.
1 parent 2695027 commit dd69597

File tree

1 file changed

+9
-36
lines changed

1 file changed

+9
-36
lines changed

src/backend/access/heap/vacuumlazy.c

+9-36
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,6 @@ typedef struct LVRelStats
125125
double new_rel_tuples; /* new estimated total # of tuples */
126126
double new_live_tuples; /* new estimated total # of live tuples */
127127
double new_dead_tuples; /* new estimated total # of dead tuples */
128-
double nleft_dead_tuples; /* # of dead tuples we left */
129-
double nleft_dead_itemids; /* # of dead item pointers we left */
130128
BlockNumber pages_removed;
131129
double tuples_deleted;
132130
BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */
@@ -427,12 +425,6 @@ heap_vacuum_rel(Relation onerel, VacuumParams *params,
427425
vacrelstats->new_rel_tuples,
428426
vacrelstats->new_dead_tuples,
429427
OldestXmin);
430-
if (vacrelstats->nleft_dead_tuples > 0 ||
431-
vacrelstats->nleft_dead_itemids > 0)
432-
appendStringInfo(&buf,
433-
_("%.0f tuples and %.0f item identifiers are left as dead.\n"),
434-
vacrelstats->nleft_dead_tuples,
435-
vacrelstats->nleft_dead_itemids);
436428
appendStringInfo(&buf,
437429
_("buffer usage: %d hits, %d misses, %d dirtied\n"),
438430
VacuumPageHit,
@@ -515,10 +507,7 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
515507
live_tuples, /* live tuples (reltuples estimate) */
516508
tups_vacuumed, /* tuples cleaned up by vacuum */
517509
nkeep, /* dead-but-not-removable tuples */
518-
nunused, /* unused item pointers */
519-
nleft_dead_tuples, /* tuples we left as dead */
520-
nleft_dead_itemids; /* item pointers we left as dead,
521-
* includes nleft_dead_tuples. */
510+
nunused; /* unused item pointers */
522511
IndexBulkDeleteResult **indstats;
523512
int i;
524513
PGRUsage ru0;
@@ -551,7 +540,6 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
551540
empty_pages = vacuumed_pages = 0;
552541
next_fsm_block_to_vacuum = (BlockNumber) 0;
553542
num_tuples = live_tuples = tups_vacuumed = nkeep = nunused = 0;
554-
nleft_dead_itemids = nleft_dead_tuples = 0;
555543

556544
indstats = (IndexBulkDeleteResult **)
557545
palloc0(nindexes * sizeof(IndexBulkDeleteResult *));
@@ -1075,7 +1063,11 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
10751063
* it were RECENTLY_DEAD. Also, if it's a heap-only
10761064
* tuple, we choose to keep it, because it'll be a lot
10771065
* cheaper to get rid of it in the next pruning pass than
1078-
* to treat it like an indexed tuple.
1066+
* to treat it like an indexed tuple. Finally, if index
1067+
* cleanup is disabled, the second heap pass will not
1068+
* execute, and the tuple will not get removed, so we
1069+
* must treat it like any other dead tuple that we choose
1070+
* to keep.
10791071
*
10801072
* If this were to happen for a tuple that actually needed
10811073
* to be deleted, we'd be in trouble, because it'd
@@ -1085,20 +1077,11 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
10851077
* preventing corruption.
10861078
*/
10871079
if (HeapTupleIsHotUpdated(&tuple) ||
1088-
HeapTupleIsHeapOnly(&tuple))
1080+
HeapTupleIsHeapOnly(&tuple) ||
1081+
params->index_cleanup == VACOPT_TERNARY_DISABLED)
10891082
nkeep += 1;
10901083
else
1091-
{
10921084
tupgone = true; /* we can delete the tuple */
1093-
1094-
/*
1095-
* Since this dead tuple will not be vacuumed and
1096-
* ignored when index cleanup is disabled we count
1097-
* count it for reporting.
1098-
*/
1099-
if (params->index_cleanup == VACOPT_TERNARY_ENABLED)
1100-
nleft_dead_tuples++;
1101-
}
11021085
all_visible = false;
11031086
break;
11041087
case HEAPTUPLE_LIVE:
@@ -1275,7 +1258,6 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
12751258
* the next vacuum will process them anyway.
12761259
*/
12771260
Assert(params->index_cleanup == VACOPT_TERNARY_DISABLED);
1278-
nleft_dead_itemids += vacrelstats->num_dead_tuples;
12791261
}
12801262

12811263
/*
@@ -1402,21 +1384,14 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
14021384
RecordPageWithFreeSpace(onerel, blkno, freespace, nblocks);
14031385
}
14041386

1405-
/* No dead tuples should be left if index cleanup is enabled */
1406-
Assert((params->index_cleanup == VACOPT_TERNARY_ENABLED &&
1407-
nleft_dead_tuples == 0 && nleft_dead_itemids == 0) ||
1408-
params->index_cleanup == VACOPT_TERNARY_DISABLED);
1409-
14101387
/* report that everything is scanned and vacuumed */
14111388
pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, blkno);
14121389

14131390
pfree(frozen);
14141391

14151392
/* save stats for use later */
14161393
vacrelstats->tuples_deleted = tups_vacuumed;
1417-
vacrelstats->new_dead_tuples = nkeep + nleft_dead_tuples;
1418-
vacrelstats->nleft_dead_tuples = nleft_dead_tuples;
1419-
vacrelstats->nleft_dead_itemids = nleft_dead_itemids;
1394+
vacrelstats->new_dead_tuples = nkeep;
14201395

14211396
/* now we can compute the new value for pg_class.reltuples */
14221397
vacrelstats->new_live_tuples = vac_estimate_reltuples(onerel,
@@ -1520,8 +1495,6 @@ lazy_scan_heap(Relation onerel, VacuumParams *params, LVRelStats *vacrelstats,
15201495
"%u pages are entirely empty.\n",
15211496
empty_pages),
15221497
empty_pages);
1523-
appendStringInfo(&buf, "%.0f tuples and %.0f item identifiers are left as dead.\n",
1524-
nleft_dead_tuples, nleft_dead_itemids);
15251498
appendStringInfo(&buf, _("%s."), pg_rusage_show(&ru0));
15261499

15271500
ereport(elevel,

0 commit comments

Comments
 (0)