Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit042c909

Browse files
committed
Produce more-optimal plans for bitmap scans on boolean columns.
The planner simplifies boolean comparisons such as "x = true" and"x = false" down to "x" and "NOT x" respectively, to have a canonicalform to ease comparisons. However, if we want to use an index on x,the index AM APIs require us to reconstitute the comparison-operatorform of the indexqual. While that works, in bitmap indexscans thecanonical form of the qual was emitted as a "filter" conditionalthough it really only needs to be a "recheck" condition, becausecreate_bitmap_scan_plan didn't recognize the equivalence of thatform with the generated indexqual. booleq() is pretty cheap so thatlikely doesn't make very much difference, but it's unsightly solet's clean it up.To fix, add a case to predicate_implied_by() to recognize theequivalence of such clauses. This is a relatively low-cost place toadd a check, and perhaps it will have additional use cases in future.Richard Guo and Tom Lane, per discussion of bug #17618 from SindySenorita.Discussion:https://postgr.es/m/17618-7a2240bfaa7e84ae@postgresql.org
1 parent05a7be9 commit042c909

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

‎contrib/btree_gin/expected/bool.out

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM test_bool WHERE i=true ORDER BY i;
9292
Sort
9393
Sort Key: i
9494
-> Bitmap Heap Scan on test_bool
95-
Filter: i
95+
Recheck Cond: i
9696
-> Bitmap Index Scan on idx_bool
9797
Index Cond: (i = true)
9898
(6 rows)
@@ -119,3 +119,15 @@ EXPLAIN (COSTS OFF) SELECT * FROM test_bool WHERE i>true ORDER BY i;
119119
Index Cond: (i > true)
120120
(6 rows)
121121

122+
-- probably sufficient to check just this one:
123+
EXPLAIN (COSTS OFF) SELECT * FROM test_bool WHERE i=false ORDER BY i;
124+
QUERY PLAN
125+
-------------------------------------------
126+
Sort
127+
Sort Key: i
128+
-> Bitmap Heap Scan on test_bool
129+
Recheck Cond: (NOT i)
130+
-> Bitmap Index Scan on idx_bool
131+
Index Cond: (i = false)
132+
(6 rows)
133+

‎contrib/btree_gin/sql/bool.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,5 @@ EXPLAIN (COSTS OFF) SELECT * FROM test_bool WHERE i<=true ORDER BY i;
2525
EXPLAIN (COSTS OFF)SELECT*FROM test_boolWHERE i=trueORDER BY i;
2626
EXPLAIN (COSTS OFF)SELECT*FROM test_boolWHERE i>=trueORDER BY i;
2727
EXPLAIN (COSTS OFF)SELECT*FROM test_boolWHERE i>trueORDER BY i;
28+
-- probably sufficient to check just this one:
29+
EXPLAIN (COSTS OFF)SELECT*FROM test_boolWHERE i=falseORDER BY i;

‎src/backend/optimizer/util/predtest.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
#include"postgres.h"
1717

18+
#include"catalog/pg_operator.h"
1819
#include"catalog/pg_proc.h"
1920
#include"catalog/pg_type.h"
2021
#include"executor/executor.h"
@@ -1093,14 +1094,20 @@ arrayexpr_cleanup_fn(PredIterInfo info)
10931094
*
10941095
* We return true if able to prove the implication, false if not.
10951096
*
1096-
* We havethree strategies for determining whether one simple clause
1097+
* We haveseveral strategies for determining whether one simple clause
10971098
* implies another:
10981099
*
10991100
* A simple and general way is to see if they are equal(); this works for any
11001101
* kind of expression, and for either implication definition. (Actually,
11011102
* there is an implied assumption that the functions in the expression are
11021103
* immutable --- but this was checked for the predicate by the caller.)
11031104
*
1105+
* Another way that always works is that for boolean x, "x = TRUE" is
1106+
* equivalent to "x", likewise "x = FALSE" is equivalent to "NOT x".
1107+
* These can be worth checking because, while we preferentially simplify
1108+
* boolean comparisons down to "x" and "NOT x", the other form has to be
1109+
* dealt with anyway in the context of index conditions.
1110+
*
11041111
* If the predicate is of the form "foo IS NOT NULL", and we are considering
11051112
* strong implication, we can conclude that the predicate is implied if the
11061113
* clause is strict for "foo", i.e., it must yield false or NULL when "foo"
@@ -1124,6 +1131,43 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause,
11241131
if (equal((Node*)predicate,clause))
11251132
return true;
11261133

1134+
/* Next see if clause is boolean equality to a constant */
1135+
if (is_opclause(clause)&&
1136+
((OpExpr*)clause)->opno==BooleanEqualOperator)
1137+
{
1138+
OpExpr*op= (OpExpr*)clause;
1139+
Node*rightop;
1140+
1141+
Assert(list_length(op->args)==2);
1142+
rightop=lsecond(op->args);
1143+
/* We might never see a null Const here, but better check anyway */
1144+
if (rightop&&IsA(rightop,Const)&&
1145+
!((Const*)rightop)->constisnull)
1146+
{
1147+
Node*leftop=linitial(op->args);
1148+
1149+
if (DatumGetBool(((Const*)rightop)->constvalue))
1150+
{
1151+
/* X = true implies X */
1152+
if (equal(predicate,leftop))
1153+
return true;
1154+
}
1155+
else
1156+
{
1157+
/* X = false implies NOT X */
1158+
if (is_notclause(predicate)&&
1159+
equal(get_notclausearg(predicate),leftop))
1160+
return true;
1161+
}
1162+
}
1163+
}
1164+
1165+
/*
1166+
* We could likewise check whether the predicate is boolean equality to a
1167+
* constant; but there are no known use-cases for that at the moment,
1168+
* assuming that the predicate has been through constant-folding.
1169+
*/
1170+
11271171
/* Next try the IS NOT NULL case */
11281172
if (!weak&&
11291173
predicate&&IsA(predicate,NullTest))

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp