From 46a0eee3006b11a15b73426c8146ed5ab32e1d62 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 28 Aug 2005 22:47:20 +0000 Subject: [PATCH] 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. --- src/backend/executor/nodeBitmapAnd.c | 12 +++++++++++- src/backend/nodes/tidbitmap.c | 11 ++++++++++- src/backend/optimizer/path/indxpath.c | 7 ++++++- src/include/nodes/tidbitmap.h | 4 +++- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c index 1d5d94fc3f..939062d4d6 100644 --- a/src/backend/executor/nodeBitmapAnd.c +++ b/src/backend/executor/nodeBitmapAnd.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapAnd.c,v 1.2 2005/04/20 15:48:36 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapAnd.c,v 1.3 2005/08/28 22:47:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -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 777bf6482d..e36a8d9806 100644 --- a/src/backend/nodes/tidbitmap.c +++ b/src/backend/nodes/tidbitmap.c @@ -23,7 +23,7 @@ * Copyright (c) 2003-2005, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/tidbitmap.c,v 1.5 2005/07/24 02:25:26 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/tidbitmap.c,v 1.6 2005/08/28 22:47:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -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 bd0b09fcfe..c689d1461e 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.187 2005/07/28 20:26:20 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.188 2005/08/28 22:47:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -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 2c90c01d81..ea5673e6f2 100644 --- a/src/include/nodes/tidbitmap.h +++ b/src/include/nodes/tidbitmap.h @@ -15,7 +15,7 @@ * * Copyright (c) 2003-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/nodes/tidbitmap.h,v 1.1 2005/04/17 22:24:02 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/tidbitmap.h,v 1.2 2005/08/28 22:47:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -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); -- 2.11.0