Skip not SOAP-supported indexes while transforming an OR clause into SAOP
authorAlexander Korotkov <akorotkov@postgresql.org>
Fri, 29 Nov 2024 07:48:29 +0000 (09:48 +0200)
committerAlexander Korotkov <akorotkov@postgresql.org>
Fri, 29 Nov 2024 07:52:12 +0000 (09:52 +0200)
There is no point in transforming OR-clauses into SAOP's if the target index
doesn't support SAOP scans anyway.  This commit adds corresponding checks
to match_orclause_to_indexcol() and group_similar_or_args().  The first check
fixes the actual bug, while the second just saves some cycles.

Reported-by: Alexander Lakhin
Discussion: https://postgr.es/m/8174de69-9e1a-0827-0e81-ef97f56a5939%40gmail.com
Author: Alena Rybakina
Reviewed-by: Ranier Vilela, Alexander Korotkov, Andrei Lepikhov
src/backend/optimizer/path/indxpath.c
src/test/regress/expected/create_index.out
src/test/regress/sql/create_index.sql

index d827fc9f4d9ffb3e4db337351048fe885b406702..5d102a0d3716f641a931a65d9e85fa46c4151c16 100644 (file)
@@ -1354,8 +1354,11 @@ group_similar_or_args(PlannerInfo *root, RelOptInfo *rel, RestrictInfo *rinfo)
                {
                        IndexOptInfo *index = (IndexOptInfo *) lfirst(lc2);
 
-                       /* Ignore index if it doesn't support bitmap scans */
-                       if (!index->amhasgetbitmap)
+                       /*
+                        * Ignore index if it doesn't support bitmap scans or SAOP
+                        * clauses.
+                        */
+                       if (!index->amhasgetbitmap || !index->amsearcharray)
                                continue;
 
                        for (colnum = 0; colnum < index->nkeycolumns; colnum++)
@@ -3248,6 +3251,10 @@ match_orclause_to_indexcol(PlannerInfo *root,
        Assert(IsA(orclause, BoolExpr));
        Assert(orclause->boolop == OR_EXPR);
 
+       /* Ignore index if it doesn't support SAOP clauses */
+       if (!index->amsearcharray)
+               return NULL;
+
        /*
         * Try to convert a list of OR-clauses to a single SAOP expression. Each
         * OR entry must be in the form: (indexkey operator constant) or (constant
index 1b0a5f0e9e1ac841a6b584fe4eef8e39c29e9a62..1904eb65bb969995f180c48ca3cfc4c41c11e976 100644 (file)
@@ -1233,6 +1233,24 @@ SELECT count(*) FROM tenk1 WHERE stringu1 = 'TVAAAA';
     14
 (1 row)
 
+-- OR-clauses shouldn't be transformed into SAOP because hash indexes don't
+-- support SAOP scans.
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT COUNT(*) FROM tenk1 WHERE stringu1 = 'TVAAAA' OR  stringu1 = 'TVAAAB';
+                                     QUERY PLAN                                     
+------------------------------------------------------------------------------------
+ Aggregate
+   ->  Bitmap Heap Scan on tenk1
+         Recheck Cond: ((stringu1 = 'TVAAAA'::name) OR (stringu1 = 'TVAAAB'::name))
+         ->  BitmapOr
+               ->  Bitmap Index Scan on hash_tuplesort_idx
+                     Index Cond: (stringu1 = 'TVAAAA'::name)
+               ->  Bitmap Index Scan on hash_tuplesort_idx
+                     Index Cond: (stringu1 = 'TVAAAB'::name)
+(8 rows)
+
+RESET enable_seqscan;
 DROP INDEX hash_tuplesort_idx;
 RESET maintenance_work_mem;
 --
index ddd0d9ad396912457334843055b225edc75435a9..c085e05f0528009bff85f8c0f5dd264dfc9bae7e 100644 (file)
@@ -372,6 +372,12 @@ CREATE INDEX hash_tuplesort_idx ON tenk1 USING hash (stringu1 name_ops) WITH (fi
 EXPLAIN (COSTS OFF)
 SELECT count(*) FROM tenk1 WHERE stringu1 = 'TVAAAA';
 SELECT count(*) FROM tenk1 WHERE stringu1 = 'TVAAAA';
+-- OR-clauses shouldn't be transformed into SAOP because hash indexes don't
+-- support SAOP scans.
+SET enable_seqscan = off;
+EXPLAIN (COSTS OFF)
+SELECT COUNT(*) FROM tenk1 WHERE stringu1 = 'TVAAAA' OR  stringu1 = 'TVAAAB';
+RESET enable_seqscan;
 DROP INDEX hash_tuplesort_idx;
 RESET maintenance_work_mem;