From bf136cf6e376ae1a636341e5c8471c55299f9122 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 22 Jan 2009 19:25:00 +0000 Subject: [PATCH] Only skip pages marked as clean in the visibility map, if the last 32 pages were marked as clean as well. The idea is to avoid defeating OS readahead by skipping a page here and there, and also makes it less likely that we miss an opportunity to advance relfrozenxid, for the sake of only a few skipped pages. --- src/backend/commands/vacuumlazy.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 63a6ffb440..4e4624cb13 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -29,7 +29,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.117 2009/01/16 13:27:23 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.118 2009/01/22 19:25:00 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -74,6 +74,12 @@ */ #define LAZY_ALLOC_TUPLES MaxHeapTuplesPerPage +/* + * Before we consider skipping a page that's marked as clean in + * visibility map, we must've seen at least this many clean pages. + */ +#define SKIP_PAGES_THRESHOLD 32 + typedef struct LVRelStats { /* hasindex = true means two-pass strategy; false means one-pass */ @@ -271,6 +277,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, int i; PGRUsage ru0; Buffer vmbuffer = InvalidBuffer; + BlockNumber all_visible_streak; pg_rusage_init(&ru0); @@ -292,6 +299,7 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, lazy_space_alloc(vacrelstats, nblocks); + all_visible_streak = 0; for (blkno = 0; blkno < nblocks; blkno++) { Buffer buf; @@ -309,7 +317,14 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, /* * Skip pages that don't require vacuuming according to the - * visibility map. + * visibility map. But only if we've seen a streak of at least + * SKIP_PAGES_THRESHOLD pages marked as clean. Since we're reading + * sequentially, the OS should be doing readahead for us and there's + * no gain in skipping a page now and then. You need a longer run of + * consecutive skipped pages before it's worthwhile. Also, skipping + * even a single page means that we can't update relfrozenxid or + * reltuples, so we only want to do it if there's a good chance to + * skip a goodly number of pages. */ if (!scan_all) { @@ -317,9 +332,15 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, visibilitymap_test(onerel, blkno, &vmbuffer); if (all_visible_according_to_vm) { - vacrelstats->scanned_all = false; - continue; + all_visible_streak++; + if (all_visible_streak >= SKIP_PAGES_THRESHOLD) + { + vacrelstats->scanned_all = false; + continue; + } } + else + all_visible_streak = 0; } vacuum_delay_point();