]> granicus.if.org Git - postgresql/commitdiff
Avoid re-checking for visibility map extension too frequently.
authorRobert Haas <rhaas@postgresql.org>
Thu, 2 Feb 2012 01:35:42 +0000 (20:35 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 2 Feb 2012 01:35:42 +0000 (20:35 -0500)
When testing bits (but not when setting or clearing them), we now
won't check whether the map has been extended.  This significantly
improves performance in the case where the visibility map doesn't
exist yet, by avoiding an extra system call per tuple.  To make
sure backends notice eventually, send an smgr inval on VM extension.

Dean Rasheed, with minor modifications by me.

src/backend/access/heap/visibilitymap.c

index 76b3a46780d43734293fdea6f7216dd94c12e28f..6505e76daedde2f70092f00556b74c7eee1b491d 100644 (file)
@@ -88,6 +88,7 @@
 #include "storage/bufmgr.h"
 #include "storage/lmgr.h"
 #include "storage/smgr.h"
+#include "utils/inval.h"
 
 
 /*#define TRACE_VISIBILITYMAP */
@@ -482,16 +483,20 @@ vm_readbuf(Relation rel, BlockNumber blkno, bool extend)
 {
        Buffer          buf;
 
+       /*
+        * We might not have opened the relation at the smgr level yet, or we might
+        * have been forced to close it by a sinval message.  The code below won't
+        * necessarily notice relation extension immediately when extend = false,
+        * so we rely on sinval messages to ensure that our ideas about the size of
+        * the map aren't too far out of date.
+        */
        RelationOpenSmgr(rel);
 
        /*
         * If we haven't cached the size of the visibility map fork yet, check it
-        * first.  Also recheck if the requested block seems to be past end, since
-        * our cached value might be stale.  (We send smgr inval messages on
-        * truncation, but not on extension.)
+        * first.
         */
-       if (rel->rd_smgr->smgr_vm_nblocks == InvalidBlockNumber ||
-               blkno >= rel->rd_smgr->smgr_vm_nblocks)
+       if (rel->rd_smgr->smgr_vm_nblocks == InvalidBlockNumber)
        {
                if (smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM))
                        rel->rd_smgr->smgr_vm_nblocks = smgrnblocks(rel->rd_smgr,
@@ -560,6 +565,7 @@ vm_extend(Relation rel, BlockNumber vm_nblocks)
 
        vm_nblocks_now = smgrnblocks(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
 
+       /* Now extend the file */
        while (vm_nblocks_now < vm_nblocks)
        {
                smgrextend(rel->rd_smgr, VISIBILITYMAP_FORKNUM, vm_nblocks_now,
@@ -567,6 +573,15 @@ vm_extend(Relation rel, BlockNumber vm_nblocks)
                vm_nblocks_now++;
        }
 
+       /*
+        * Send a shared-inval message to force other backends to close any smgr
+        * references they may have for this rel, which we are about to change.
+        * This is a useful optimization because it means that backends don't have
+        * to keep checking for creation or extension of the file, which happens
+        * infrequently.
+        */
+       CacheInvalidateSmgr(rel->rd_smgr->smgr_rnode);
+
        /* Update local cache with the up-to-date size */
        rel->rd_smgr->smgr_vm_nblocks = vm_nblocks_now;