diff options
author | Tom Lane | 2005-08-28 22:47:20 +0000 |
---|---|---|
committer | Tom Lane | 2005-08-28 22:47:20 +0000 |
commit | ae9a666708e6f47ad31c40e7a50eaa1d2b0ab840 (patch) | |
tree | 9d166e9bf873517cbacfffefc775392da863589f | |
parent | 593a687df22caf023d433b7ec0676c0db4a022bd (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.c | 10 | ||||
-rw-r--r-- | src/backend/nodes/tidbitmap.c | 9 | ||||
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 5 | ||||
-rw-r--r-- | src/include/nodes/tidbitmap.h | 2 |
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); |