diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/access/heap/vacuumlazy.c | 97 | ||||
-rw-r--r-- | src/backend/commands/analyze.c | 3 | ||||
-rw-r--r-- | src/backend/commands/vacuum.c | 9 | ||||
-rw-r--r-- | src/include/commands/vacuum.h | 2 |
4 files changed, 82 insertions, 29 deletions
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index e676969ed1c..fed25f49294 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -199,6 +199,7 @@ typedef struct LVRelState BlockNumber frozenskipped_pages; /* # frozen pages skipped via VM */ BlockNumber removed_pages; /* # pages removed by relation truncation */ BlockNumber lpdead_item_pages; /* # pages with LP_DEAD items */ + BlockNumber missed_dead_pages; /* # pages with missed dead tuples */ BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */ /* Statistics output by us, for table */ @@ -212,8 +213,8 @@ typedef struct LVRelState /* Counters that follow are only for scanned_pages */ int64 tuples_deleted; /* # deleted from table */ int64 lpdead_items; /* # deleted from indexes */ - int64 new_dead_tuples; /* new estimated total # of dead items in - * table */ + int64 recently_dead_tuples; /* # dead, but not yet removable */ + int64 missed_dead_tuples; /* # removable, but not removed */ int64 num_tuples; /* total number of nonremovable tuples */ int64 live_tuples; /* live tuples (reltuples estimate) */ } LVRelState; @@ -318,6 +319,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, write_rate; bool aggressive, skipwithvm; + bool frozenxid_updated, + minmulti_updated; BlockNumber orig_rel_pages; char **indnames = NULL; TransactionId xidFullScanLimit; @@ -539,9 +542,11 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, { /* Cannot advance relfrozenxid/relminmxid */ Assert(!aggressive); + frozenxid_updated = minmulti_updated = false; vac_update_relstats(rel, new_rel_pages, new_live_tuples, new_rel_allvisible, vacrel->nindexes > 0, - InvalidTransactionId, InvalidMultiXactId, false); + InvalidTransactionId, InvalidMultiXactId, + NULL, NULL, false); } else { @@ -549,7 +554,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, orig_rel_pages); vac_update_relstats(rel, new_rel_pages, new_live_tuples, new_rel_allvisible, vacrel->nindexes > 0, - FreezeLimit, MultiXactCutoff, false); + FreezeLimit, MultiXactCutoff, + &frozenxid_updated, &minmulti_updated, false); } /* @@ -565,7 +571,8 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, pgstat_report_vacuum(RelationGetRelid(rel), rel->rd_rel->relisshared, Max(new_live_tuples, 0), - vacrel->new_dead_tuples); + vacrel->recently_dead_tuples + + vacrel->missed_dead_tuples); pgstat_progress_end_command(); if (instrument) @@ -578,6 +585,7 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, { StringInfoData buf; char *msgfmt; + int32 diff; TimestampDifference(starttime, endtime, &secs, &usecs); @@ -629,16 +637,40 @@ heap_vacuum_rel(Relation rel, VacuumParams *params, vacrel->relnamespace, vacrel->relname, vacrel->num_index_scans); - appendStringInfo(&buf, _("pages: %u removed, %u remain, %u skipped frozen\n"), + appendStringInfo(&buf, _("pages: %u removed, %u remain, %u scanned (%.2f%% of total)\n"), vacrel->removed_pages, vacrel->rel_pages, - vacrel->frozenskipped_pages); + vacrel->scanned_pages, + orig_rel_pages == 0 ? 0 : + 100.0 * vacrel->scanned_pages / orig_rel_pages); appendStringInfo(&buf, - _("tuples: %lld removed, %lld remain, %lld are dead but not yet removable, oldest xmin: %u\n"), + _("tuples: %lld removed, %lld remain, %lld are dead but not yet removable\n"), (long long) vacrel->tuples_deleted, (long long) vacrel->new_rel_tuples, - (long long) vacrel->new_dead_tuples, - OldestXmin); + (long long) vacrel->recently_dead_tuples); + if (vacrel->missed_dead_tuples > 0) + appendStringInfo(&buf, + _("tuples missed: %lld dead from %u pages not removed due to cleanup lock contention\n"), + (long long) vacrel->missed_dead_tuples, + vacrel->missed_dead_pages); + diff = (int32) (ReadNextTransactionId() - OldestXmin); + appendStringInfo(&buf, + _("removable cutoff: %u, older by %d xids when operation ended\n"), + OldestXmin, diff); + if (frozenxid_updated) + { + diff = (int32) (FreezeLimit - vacrel->relfrozenxid); + appendStringInfo(&buf, + _("new relfrozenxid: %u, which is %d xids ahead of previous value\n"), + FreezeLimit, diff); + } + if (minmulti_updated) + { + diff = (int32) (MultiXactCutoff - vacrel->relminmxid); + appendStringInfo(&buf, + _("new relminmxid: %u, which is %d mxids ahead of previous value\n"), + MultiXactCutoff, diff); + } if (orig_rel_pages > 0) { if (vacrel->do_index_vacuuming) @@ -779,13 +811,15 @@ lazy_scan_heap(LVRelState *vacrel, int nworkers) vacrel->frozenskipped_pages = 0; vacrel->removed_pages = 0; vacrel->lpdead_item_pages = 0; + vacrel->missed_dead_pages = 0; vacrel->nonempty_pages = 0; /* Initialize instrumentation counters */ vacrel->num_index_scans = 0; vacrel->tuples_deleted = 0; vacrel->lpdead_items = 0; - vacrel->new_dead_tuples = 0; + vacrel->recently_dead_tuples = 0; + vacrel->missed_dead_tuples = 0; vacrel->num_tuples = 0; vacrel->live_tuples = 0; @@ -1331,7 +1365,8 @@ lazy_scan_heap(LVRelState *vacrel, int nworkers) * (unlikely) scenario that new_live_tuples is -1, take it as zero. */ vacrel->new_rel_tuples = - Max(vacrel->new_live_tuples, 0) + vacrel->new_dead_tuples; + Max(vacrel->new_live_tuples, 0) + vacrel->recently_dead_tuples + + vacrel->missed_dead_tuples; /* * Release any remaining pin on visibility map page. @@ -1539,7 +1574,7 @@ lazy_scan_prune(LVRelState *vacrel, HTSV_Result res; int tuples_deleted, lpdead_items, - new_dead_tuples, + recently_dead_tuples, num_tuples, live_tuples; int nnewlpdead; @@ -1556,7 +1591,7 @@ retry: /* Initialize (or reset) page-level counters */ tuples_deleted = 0; lpdead_items = 0; - new_dead_tuples = 0; + recently_dead_tuples = 0; num_tuples = 0; live_tuples = 0; @@ -1715,11 +1750,11 @@ retry: case HEAPTUPLE_RECENTLY_DEAD: /* - * If tuple is recently deleted then we must not remove it - * from relation. (We only remove items that are LP_DEAD from + * If tuple is recently dead then we must not remove it from + * the relation. (We only remove items that are LP_DEAD from * pruning.) */ - new_dead_tuples++; + recently_dead_tuples++; prunestate->all_visible = false; break; case HEAPTUPLE_INSERT_IN_PROGRESS: @@ -1895,7 +1930,7 @@ retry: /* Finally, add page-local counts to whole-VACUUM counts */ vacrel->tuples_deleted += tuples_deleted; vacrel->lpdead_items += lpdead_items; - vacrel->new_dead_tuples += new_dead_tuples; + vacrel->recently_dead_tuples += recently_dead_tuples; vacrel->num_tuples += num_tuples; vacrel->live_tuples += live_tuples; } @@ -1932,7 +1967,8 @@ lazy_scan_noprune(LVRelState *vacrel, int lpdead_items, num_tuples, live_tuples, - new_dead_tuples; + recently_dead_tuples, + missed_dead_tuples; HeapTupleHeader tupleheader; OffsetNumber deadoffsets[MaxHeapTuplesPerPage]; @@ -1944,7 +1980,8 @@ lazy_scan_noprune(LVRelState *vacrel, lpdead_items = 0; num_tuples = 0; live_tuples = 0; - new_dead_tuples = 0; + recently_dead_tuples = 0; + missed_dead_tuples = 0; maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; @@ -2018,16 +2055,15 @@ lazy_scan_noprune(LVRelState *vacrel, /* * There is some useful work for pruning to do, that won't be * done due to failure to get a cleanup lock. - * - * TODO Add dedicated instrumentation for this case */ + missed_dead_tuples++; break; case HEAPTUPLE_RECENTLY_DEAD: /* - * Count in new_dead_tuples, just like lazy_scan_prune + * Count in recently_dead_tuples, just like lazy_scan_prune */ - new_dead_tuples++; + recently_dead_tuples++; break; case HEAPTUPLE_INSERT_IN_PROGRESS: @@ -2063,7 +2099,7 @@ lazy_scan_noprune(LVRelState *vacrel, */ *hastup = true; num_tuples += lpdead_items; - /* TODO HEAPTUPLE_DEAD style instrumentation needed here, too */ + missed_dead_tuples += lpdead_items; } *recordfreespace = true; @@ -2112,9 +2148,12 @@ lazy_scan_noprune(LVRelState *vacrel, /* * Finally, add relevant page-local counts to whole-VACUUM counts */ - vacrel->new_dead_tuples += new_dead_tuples; + vacrel->recently_dead_tuples += recently_dead_tuples; + vacrel->missed_dead_tuples += missed_dead_tuples; vacrel->num_tuples += num_tuples; vacrel->live_tuples += live_tuples; + if (missed_dead_tuples > 0) + vacrel->missed_dead_pages++; /* Caller won't need to call lazy_scan_prune with same page */ return true; @@ -2193,8 +2232,8 @@ lazy_vacuum(LVRelState *vacrel) * dead_items space is not CPU cache resident. * * We don't take any special steps to remember the LP_DEAD items (such - * as counting them in new_dead_tuples report to the stats collector) - * when the optimization is applied. Though the accounting used in + * as counting them in our final report to the stats collector) when + * the optimization is applied. Though the accounting used in * analyze.c's acquire_sample_rows() will recognize the same LP_DEAD * items as dead rows in its own stats collector report, that's okay. * The discrepancy should be negligible. If this optimization is ever @@ -3321,7 +3360,7 @@ update_index_statistics(LVRelState *vacrel) false, InvalidTransactionId, InvalidMultiXactId, - false); + NULL, NULL, false); } } diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index a0da998c2ea..736479295ad 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -645,6 +645,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params, hasindex, InvalidTransactionId, InvalidMultiXactId, + NULL, NULL, in_outer_xact); /* Same for indexes */ @@ -661,6 +662,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params, false, InvalidTransactionId, InvalidMultiXactId, + NULL, NULL, in_outer_xact); } } @@ -673,6 +675,7 @@ do_analyze_rel(Relation onerel, VacuumParams *params, vac_update_relstats(onerel, -1, totalrows, 0, hasindex, InvalidTransactionId, InvalidMultiXactId, + NULL, NULL, in_outer_xact); } diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index d1dadc54e47..37413dd43e9 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1315,6 +1315,7 @@ vac_update_relstats(Relation relation, BlockNumber num_all_visible_pages, bool hasindex, TransactionId frozenxid, MultiXactId minmulti, + bool *frozenxid_updated, bool *minmulti_updated, bool in_outer_xact) { Oid relid = RelationGetRelid(relation); @@ -1390,22 +1391,30 @@ vac_update_relstats(Relation relation, * This should match vac_update_datfrozenxid() concerning what we consider * to be "in the future". */ + if (frozenxid_updated) + *frozenxid_updated = false; if (TransactionIdIsNormal(frozenxid) && pgcform->relfrozenxid != frozenxid && (TransactionIdPrecedes(pgcform->relfrozenxid, frozenxid) || TransactionIdPrecedes(ReadNextTransactionId(), pgcform->relfrozenxid))) { + if (frozenxid_updated) + *frozenxid_updated = true; pgcform->relfrozenxid = frozenxid; dirty = true; } /* Similarly for relminmxid */ + if (minmulti_updated) + *minmulti_updated = false; if (MultiXactIdIsValid(minmulti) && pgcform->relminmxid != minmulti && (MultiXactIdPrecedes(pgcform->relminmxid, minmulti) || MultiXactIdPrecedes(ReadNextMultiXactId(), pgcform->relminmxid))) { + if (minmulti_updated) + *minmulti_updated = true; pgcform->relminmxid = minmulti; dirty = true; } diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 5d0bdfa4279..e5e548d6b9a 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -283,6 +283,8 @@ extern void vac_update_relstats(Relation relation, bool hasindex, TransactionId frozenxid, MultiXactId minmulti, + bool *frozenxid_updated, + bool *minmulti_updated, bool in_outer_xact); extern void vacuum_set_xid_limits(Relation rel, int freeze_min_age, int freeze_table_age, |