Add bound check before bsearch() for performance
authorPeter Eisentraut
Wed, 10 Mar 2021 14:19:37 +0000 (15:19 +0100)
committerPeter Eisentraut
Wed, 10 Mar 2021 14:19:37 +0000 (15:19 +0100)
In the current lazy vacuum implementation, some index AMs such as
btree indexes call lazy_tid_reaped() for each index tuple during
ambulkdelete to check if the index tuple points to the (collected)
garbage tuple.  In that function, we simply call bsearch(), but we
should be able to know the result without bsearch() if the index tuple
points to the heap tuple that is out of range of the collected garbage
tuples.  Therefore, add a simple bound check before resorting to
bsearch().  Testing has shown that this can give significant
performance benefits.

Author: Masahiko Sawada 
Discussion: https://www.postgresql.org/message-id/flat/CA+fd4k76j8jKzJzcx8UqEugvayaMSnQz0iLUt_XgBp-_-bd22A@mail.gmail.com

src/backend/access/heap/vacuumlazy.c

index d8f847b0e6673c435168ca4304f15f23aaac9162..4b65205cd1344b212b5b0d3258887f2e202f51b8 100644 (file)
@@ -61,6 +61,7 @@
 #include "access/visibilitymap.h"
 #include "access/xact.h"
 #include "access/xlog.h"
+#include "catalog/index.h"
 #include "catalog/storage.h"
 #include "commands/dbcommands.h"
 #include "commands/progress.h"
@@ -2923,8 +2924,24 @@ static bool
 lazy_tid_reaped(ItemPointer itemptr, void *state)
 {
    LVDeadTuples *dead_tuples = (LVDeadTuples *) state;
+   int64       litem,
+               ritem,
+               item;
    ItemPointer res;
 
+   litem = itemptr_encode(&dead_tuples->itemptrs[0]);
+   ritem = itemptr_encode(&dead_tuples->itemptrs[dead_tuples->num_tuples - 1]);
+   item = itemptr_encode(itemptr);
+
+   /*
+    * Doing a simple bound check before bsearch() is useful to avoid the
+    * extra cost of bsearch(), especially if dead tuples on the heap are
+    * concentrated in a certain range.  Since this function is called for
+    * every index tuple, it pays to be really fast.
+    */
+   if (item < litem || item > ritem)
+       return false;
+
    res = (ItemPointer) bsearch((void *) itemptr,
                                (void *) dead_tuples->itemptrs,
                                dead_tuples->num_tuples,