On Thu, Aug 25, 2016 at 1:41 AM, Anastasia Lubennikova
<lubennikov...@gmail.com> wrote:
> The following review has been posted through the commitfest application:
> make installcheck-world:  tested, passed
> Implements feature:       not tested
> Spec compliant:           not tested
> Documentation:            not tested
>
> Hi,
> I haven't tested the performance yet, but the patch itself looks pretty good
> and reasonable improvement.
> I have a question about removing the comment. It seems to be really tricky
> moment. How do we know that all-frozen block hasn't changed since the
> moment we checked it?

I think that we don't need to check whether all-frozen block hasn't
changed since we checked it.
Even if the all-frozen block has changed after we saw it as an
all-frozen page, we can update the relfrozenxid.
Because any new XIDs just added to that page are newer than the
GlobalXmin we computed.

Am I missing something?

In this patch, since we count the number of all-frozen page even
during not an aggresive scan, I thought that we don't need to check
whether these blocks were all-frozen pages.

> I'm going to test the performance this week.
> I wonder if you could send a test script or describe the steps to test it?

This optimization reduces the number of scanning visibility map when
table is almost visible or frozen..
So it would be effective for very large table (more than several
hundreds GB) which is almost all-visible or all-frozen pages.

For example,
1. Create very large table.
2. Execute VACUUM FREEZE to freeze all pages of table.
3. Measure the execution time of VACUUM FREEZE.
    I hope that the second VACUUM FREEZE become fast a little.

I modified the comment, and attached v2 patch.

Regards,

--
Masahiko Sawada
diff --git a/src/backend/commands/vacuumlazy.c 
b/src/backend/commands/vacuumlazy.c
index 231e92d..226dc83 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -471,6 +471,8 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
                PROGRESS_VACUUM_MAX_DEAD_TUPLES
        };
        int64           initprog_val[3];
+       BlockNumber     n_skipped;
+       BlockNumber n_all_frozen;
 
        pg_rusage_init(&ru0);
 
@@ -501,6 +503,9 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
        initprog_val[2] = vacrelstats->max_dead_tuples;
        pgstat_progress_update_multi_param(3, initprog_index, initprog_val);
 
+       n_skipped = 0;
+       n_all_frozen = 0;
+
        /*
         * Except when aggressive is set, we want to skip pages that are
         * all-visible according to the visibility map, but only when we can 
skip
@@ -558,14 +563,20 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
                        {
                                if ((vmstatus & VISIBILITYMAP_ALL_FROZEN) == 0)
                                        break;
+                               n_all_frozen++;
                        }
                        else
                        {
                                if ((vmstatus & VISIBILITYMAP_ALL_VISIBLE) == 0)
                                        break;
+
+                               /* Count the number of all-frozen pages */
+                               if (vmstatus & VISIBILITYMAP_ALL_FROZEN)
+                                       n_all_frozen++;
                        }
                        vacuum_delay_point();
                        next_unskippable_block++;
+                       n_skipped++;
                }
        }
 
@@ -574,7 +585,8 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
        else
                skipping_blocks = false;
 
-       for (blkno = 0; blkno < nblocks; blkno++)
+       blkno = 0;
+       while (blkno < nblocks)
        {
                Buffer          buf;
                Page            page;
@@ -592,18 +604,22 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
                TransactionId visibility_cutoff_xid = InvalidTransactionId;
 
                /* see note above about forcing scanning of last page */
-#define FORCE_CHECK_PAGE() \
-               (blkno == nblocks - 1 && should_attempt_truncation(vacrelstats))
+#define FORCE_CHECK_PAGE(blk) \
+               ((blk) == nblocks - 1 && should_attempt_truncation(vacrelstats))
 
                pgstat_progress_update_param(PROGRESS_VACUUM_HEAP_BLKS_SCANNED, 
blkno);
 
                if (blkno == next_unskippable_block)
                {
+                       n_skipped = 0;
+                       n_all_frozen = 0;
+
                        /* Time to advance next_unskippable_block */
                        next_unskippable_block++;
                        if ((options & VACOPT_DISABLE_PAGE_SKIPPING) == 0)
                        {
-                               while (next_unskippable_block < nblocks)
+                               while (next_unskippable_block < nblocks &&
+                                          
!FORCE_CHECK_PAGE(next_unskippable_block))
                                {
                                        uint8           vmskipflags;
 
@@ -614,14 +630,22 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
                                        {
                                                if ((vmskipflags & 
VISIBILITYMAP_ALL_FROZEN) == 0)
                                                        break;
+
+                                               /* Count the number of 
all-frozen pages */
+                                               n_all_frozen++;
                                        }
                                        else
                                        {
                                                if ((vmskipflags & 
VISIBILITYMAP_ALL_VISIBLE) == 0)
                                                        break;
+
+                                               /* Count the number of 
all-frozen pages */
+                                               if (vmskipflags & 
VISIBILITYMAP_ALL_FROZEN)
+                                                       n_all_frozen++;
                                        }
                                        vacuum_delay_point();
                                        next_unskippable_block++;
+                                       n_skipped++;
                                }
                        }
 
@@ -646,26 +670,32 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
                else
                {
                        /*
-                        * The current block is potentially skippable; if we've 
seen a
-                        * long enough run of skippable blocks to justify 
skipping it, and
-                        * we're not forced to check it, then go ahead and skip.
-                        * Otherwise, the page must be at least all-visible if 
not
-                        * all-frozen, so we can set 
all_visible_according_to_vm = true.
+                        * The current block is the first block of continuous 
skippable blocks,
+                        * and we know that how many blocks we can skip to 
scan. If we've
+                        * seen a long enough run of skippable blocks to 
justify skipping it,
+                        * then go ahead and skip. Otherwise, the page must be 
at least all-visible
+                        * if not all-frozen, so we can set 
all_visible_according_to_vm = true.
                         */
-                       if (skipping_blocks && !FORCE_CHECK_PAGE())
+                       if (skipping_blocks)
                        {
                                /*
+                                * We know that there are n_skipped pages by 
the visibilitymap
+                                * scan we did just before.
+                                *
                                 * Tricky, tricky.  If this is in aggressive 
vacuum, the page
                                 * must have been all-frozen at the time we 
checked whether it
                                 * was skippable, but it might not be any more. 
 We must be
                                 * careful to count it as a skipped all-frozen 
page in that
                                 * case, or else we'll think we can't update 
relfrozenxid and
-                                * relminmxid.  If it's not an aggressive 
vacuum, we don't
-                                * know whether it was all-frozen, so we have 
to recheck; but
-                                * in this case an approximate answer is OK.
+                                * relminmxid.  Even if it's not an aggressive 
vacuum, we know
+                                * the number of all-frozen pages in this 
all-visible blocks,
+                                * so we don't need to recheck it.
                                 */
-                               if (aggressive || VM_ALL_FROZEN(onerel, blkno, 
&vmbuffer))
-                                       vacrelstats->frozenskipped_pages++;
+                               vacrelstats->frozenskipped_pages += 
n_all_frozen;
+
+                               /* Jump to the next unskippable block directly 
*/
+                               blkno += n_skipped;
+
                                continue;
                        }
                        all_visible_according_to_vm = true;
@@ -760,10 +790,11 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
                         * it's OK to skip vacuuming pages we get a lock 
conflict on. They
                         * will be dealt with in some future vacuum.
                         */
-                       if (!aggressive && !FORCE_CHECK_PAGE())
+                       if (!aggressive && !FORCE_CHECK_PAGE(blkno))
                        {
                                ReleaseBuffer(buf);
                                vacrelstats->pinskipped_pages++;
+                               blkno++;
                                continue;
                        }
 
@@ -791,6 +822,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
                                vacrelstats->pinskipped_pages++;
                                if (hastup)
                                        vacrelstats->nonempty_pages = blkno + 1;
+                               blkno++;
                                continue;
                        }
                        if (!aggressive)
@@ -803,6 +835,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
                                vacrelstats->pinskipped_pages++;
                                if (hastup)
                                        vacrelstats->nonempty_pages = blkno + 1;
+                               blkno++;
                                continue;
                        }
                        LockBuffer(buf, BUFFER_LOCK_UNLOCK);
@@ -853,6 +886,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
                        UnlockReleaseBuffer(buf);
 
                        RecordPageWithFreeSpace(onerel, blkno, freespace);
+                       blkno++;
                        continue;
                }
 
@@ -892,6 +926,7 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
 
                        UnlockReleaseBuffer(buf);
                        RecordPageWithFreeSpace(onerel, blkno, freespace);
+                       blkno++;
                        continue;
                }
 
@@ -1239,6 +1274,8 @@ lazy_scan_heap(Relation onerel, int options, LVRelStats 
*vacrelstats,
                 */
                if (vacrelstats->num_dead_tuples == prev_dead_count)
                        RecordPageWithFreeSpace(onerel, blkno, freespace);
+
+               blkno++;
        }
 
        /* report that everything is scanned and vacuumed */
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to