Tweak nodeBitmapAnd to stop evaluating sub-plan scans if it finds it's
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 28 Aug 2005 22:47:20 +0000 (22:47 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 28 Aug 2005 22:47:20 +0000 (22:47 +0000)
got an empty bitmap after any step; the remaining subplans can no longer
affect the result.  Per a suggestion from Ilia Kantor.

src/backend/executor/nodeBitmapAnd.c
src/backend/nodes/tidbitmap.c
src/backend/optimizer/path/indxpath.c
src/include/nodes/tidbitmap.h

index 2f23a1ae0449c011264ad3bc5f4a17e3d82ec954..f6044c4a857644fc32ff7f1570175c0be7ed51a2 100644 (file)
@@ -143,6 +143,16 @@ MultiExecBitmapAnd(BitmapAndState *node)
                        tbm_intersect(result, subresult);
                        tbm_free(subresult);
                }
+
+               /*
+                * If at any stage we have a completely empty bitmap, we can fall
+                * out without evaluating the remaining subplans, since ANDing them
+                * can no longer change the result.  (Note: the fact that indxpath.c
+                * orders the subplans by selectivity should make this case more
+                * likely to occur.)
+                */
+               if (tbm_is_empty(result))
+                       break;
        }
 
        if (result == NULL)
index 095138c8ab9b70998352c8afcd61f1d4e5be114e..1064a38c3482e6413cecfaabbdea221f149575ed 100644 (file)
@@ -510,6 +510,15 @@ tbm_intersect_page(TIDBitmap *a, PagetableEntry *apage, const TIDBitmap *b)
        }
 }
 
+/*
+ * tbm_is_empty - is a TIDBitmap completely empty?
+ */
+bool
+tbm_is_empty(const TIDBitmap *tbm)
+{
+       return (tbm->nentries == 0);
+}
+
 /*
  * tbm_begin_iterate - prepare to iterate through a TIDBitmap
  *
index 2fdfe97896fc13d57267359bef729b44ae4c5510..bb6b73faf30d7a48a805e3fe4928b7474ba4588b 100644 (file)
@@ -538,6 +538,11 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths)
         * cases, the partial index will sort before competing non-partial
         * indexes and so it makes the right choice, but perhaps we need to
         * work harder.
+        *
+        * Note: outputting the selected sub-paths in selectivity order is a good
+        * thing even if we weren't using that as part of the selection method,
+        * because it makes the short-circuit case in MultiExecBitmapAnd() more
+        * likely to apply.
         */
 
        /* Convert list to array so we can apply qsort */
index 656fd8e4679f586bfaa7f26c49c554357e6b54ae..6962c8d070c7eb6a18ceefb09f3993f830a4eaa4 100644 (file)
@@ -49,6 +49,8 @@ extern void tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids);
 extern void tbm_union(TIDBitmap *a, const TIDBitmap *b);
 extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b);
 
+extern bool tbm_is_empty(const TIDBitmap *tbm);
+
 extern void tbm_begin_iterate(TIDBitmap *tbm);
 extern TBMIterateResult *tbm_iterate(TIDBitmap *tbm);