Only skip pages marked as clean in the visibility map, if the last 32
authorHeikki Linnakangas
Thu, 22 Jan 2009 19:25:00 +0000 (19:25 +0000)
committerHeikki Linnakangas
Thu, 22 Jan 2009 19:25:00 +0000 (19:25 +0000)
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

index 63a6ffb440a8321ab7a1c7c7eb48fb6ebeaa11c7..4e4624cb132fa1f92b5080012cc6060800d2013a 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
  */
 #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();