summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2005-08-28 22:47:20 +0000
committerTom Lane2005-08-28 22:47:20 +0000
commitae9a666708e6f47ad31c40e7a50eaa1d2b0ab840 (patch)
tree9d166e9bf873517cbacfffefc775392da863589f
parent593a687df22caf023d433b7ec0676c0db4a022bd (diff)
Tweak nodeBitmapAnd to stop evaluating sub-plan scans if it finds it's
got an empty bitmap after any step; the remaining subplans can no longer affect the result. Per a suggestion from Ilia Kantor.
-rw-r--r--src/backend/executor/nodeBitmapAnd.c10
-rw-r--r--src/backend/nodes/tidbitmap.c9
-rw-r--r--src/backend/optimizer/path/indxpath.c5
-rw-r--r--src/include/nodes/tidbitmap.h2
4 files changed, 26 insertions, 0 deletions
diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c
index 2f23a1ae04..f6044c4a85 100644
--- a/src/backend/executor/nodeBitmapAnd.c
+++ b/src/backend/executor/nodeBitmapAnd.c
@@ -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)
diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c
index 095138c8ab..1064a38c34 100644
--- a/src/backend/nodes/tidbitmap.c
+++ b/src/backend/nodes/tidbitmap.c
@@ -511,6 +511,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
*
* NB: after this is called, it is no longer allowed to modify the contents
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 2fdfe97896..bb6b73faf3 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -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 */
diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h
index 656fd8e467..6962c8d070 100644
--- a/src/include/nodes/tidbitmap.h
+++ b/src/include/nodes/tidbitmap.h
@@ -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);