diff options
| author | Alexander Korotkov | 2025-02-04 21:21:49 +0000 |
|---|---|---|
| committer | Alexander Korotkov | 2025-02-04 21:21:49 +0000 |
| commit | 627d63419e22054551327216d2b2de3e6977fade (patch) | |
| tree | d414dae409a40a45c1881bc79bf0a975df3a5b01 /src/test | |
| parent | 23ef119f58e3eaa29bedc69320fd61b108ab8c10 (diff) | |
Allow usage of match_orclause_to_indexcol() for joins
This commit allows transformation of OR-clauses into SAOP's for index scans
within nested loop joins. That required the following changes.
1. Make match_orclause_to_indexcol() and group_similar_or_args() understand
const-ness in the same way as match_opclause_to_indexcol(). This
generally makes our approach more uniform.
2. Make match_join_clauses_to_index() pass OR-clauses to
match_clause_to_index().
3. Also switch match_join_clauses_to_index() to use list_append_unique_ptr()
for adding clauses to *joinorclauses. That avoids possible duplicates
when processing the same clauses with different indexes. Previously such
duplicates were elimited in match_clause_to_index(), but now
group_similar_or_args() each time generates distinct copies of grouped
OR clauses.
Discussion: https://postgr.es/m/CAPpHfdv%2BjtNwofg-p5z86jLYZUTt6tR17Wy00ta0dL%3DwHQN3ZA%40mail.gmail.com
Reviewed-by: Andrei Lepikhov <lepihov@gmail.com>
Reviewed-by: Alena Rybakina <a.rybakina@postgrespro.ru>
Reviewed-by: Pavel Borisov <pashkin.elfe@gmail.com>
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/regress/expected/create_index.out | 32 | ||||
| -rw-r--r-- | src/test/regress/expected/join.out | 51 | ||||
| -rw-r--r-- | src/test/regress/expected/partition_join.out | 12 | ||||
| -rw-r--r-- | src/test/regress/sql/create_index.sql | 9 | ||||
| -rw-r--r-- | src/test/regress/sql/join.sql | 18 |
5 files changed, 109 insertions, 13 deletions
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out index 8011c141bf8..bd5f002cf20 100644 --- a/src/test/regress/expected/create_index.out +++ b/src/test/regress/expected/create_index.out @@ -2007,6 +2007,27 @@ SELECT * FROM tenk1 (2 rows) EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 t1 + WHERE t1.thousand = 42 OR t1.thousand = (SELECT t2.tenthous FROM tenk1 t2 WHERE t2.thousand = t1.tenthous + 1 LIMIT 1); + QUERY PLAN +---------------------------------------------------------------------------- + Aggregate + -> Index Only Scan using tenk1_thous_tenthous on tenk1 t1 + Filter: ((thousand = 42) OR (thousand = (SubPlan 1))) + SubPlan 1 + -> Limit + -> Index Only Scan using tenk1_thous_tenthous on tenk1 t2 + Index Cond: (thousand = (t1.tenthous + 1)) +(7 rows) + +SELECT count(*) FROM tenk1 t1 + WHERE t1.thousand = 42 OR t1.thousand = (SELECT t2.tenthous FROM tenk1 t2 WHERE t2.thousand = t1.tenthous + 1 LIMIT 1); + count +------- + 10 +(1 row) + +EXPLAIN (COSTS OFF) SELECT count(*) FROM tenk1 WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); QUERY PLAN @@ -3256,6 +3277,17 @@ CREATE STATISTICS t_a_b_stat (mcv) ON a, b FROM bitmap_split_or; CREATE STATISTICS t_b_c_stat (mcv) ON b, c FROM bitmap_split_or; ANALYZE bitmap_split_or; EXPLAIN (COSTS OFF) +SELECT * FROM bitmap_split_or t1, bitmap_split_or t2 +WHERE t1.a = t2.b OR t1.a = 2; + QUERY PLAN +-------------------------------------------------------- + Nested Loop + -> Seq Scan on bitmap_split_or t2 + -> Index Scan using t_a_b_idx on bitmap_split_or t1 + Index Cond: (a = ANY (ARRAY[t2.b, 2])) +(4 rows) + +EXPLAIN (COSTS OFF) SELECT * FROM bitmap_split_or WHERE a = 1 AND (b = 1 OR b = 2) AND c = 2; QUERY PLAN ------------------------------------------------------------------ diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 079fcf46f0d..3ffc066b1f8 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -3849,14 +3849,11 @@ where q1 = thousand or q2 = thousand; -> Seq Scan on q2 -> Bitmap Heap Scan on tenk1 Recheck Cond: ((q1.q1 = thousand) OR (q2.q2 = thousand)) - -> BitmapOr - -> Bitmap Index Scan on tenk1_thous_tenthous - Index Cond: (thousand = q1.q1) - -> Bitmap Index Scan on tenk1_thous_tenthous - Index Cond: (thousand = q2.q2) + -> Bitmap Index Scan on tenk1_thous_tenthous + Index Cond: (thousand = ANY (ARRAY[q1.q1, q2.q2])) -> Hash -> Seq Scan on int4_tbl -(15 rows) +(12 rows) explain (costs off) select * from @@ -8239,3 +8236,45 @@ GROUP BY s.c1, s.c2; (7 rows) DROP TABLE group_tbl; +-- +-- Test for a nested loop join involving index scan, transforming OR-clauses +-- to SAOP. +-- +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM tenk1 t1, tenk1 t2 +WHERE t2.thousand = t1.tenthous OR t2.thousand = t1.unique1 OR t2.thousand = t1.unique2; + QUERY PLAN +----------------------------------------------------------------------------------------- + Aggregate + -> Nested Loop + -> Seq Scan on tenk1 t1 + -> Index Only Scan using tenk1_thous_tenthous on tenk1 t2 + Index Cond: (thousand = ANY (ARRAY[t1.tenthous, t1.unique1, t1.unique2])) +(5 rows) + +SELECT COUNT(*) FROM tenk1 t1, tenk1 t2 +WHERE t2.thousand = t1.tenthous OR t2.thousand = t1.unique1 OR t2.thousand = t1.unique2; + count +------- + 20000 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM onek t1 LEFT JOIN tenk1 t2 + ON (t2.thousand = t1.tenthous OR t2.thousand = t1.thousand); + QUERY PLAN +------------------------------------------------------------------------------ + Aggregate + -> Nested Loop Left Join + -> Seq Scan on onek t1 + -> Index Only Scan using tenk1_thous_tenthous on tenk1 t2 + Index Cond: (thousand = ANY (ARRAY[t1.tenthous, t1.thousand])) +(5 rows) + +SELECT COUNT(*) FROM onek t1 LEFT JOIN tenk1 t2 + ON (t2.thousand = t1.tenthous OR t2.thousand = t1.thousand); + count +------- + 19000 +(1 row) + diff --git a/src/test/regress/expected/partition_join.out b/src/test/regress/expected/partition_join.out index 108f9ecb445..af468682a2d 100644 --- a/src/test/regress/expected/partition_join.out +++ b/src/test/regress/expected/partition_join.out @@ -2533,24 +2533,24 @@ where not exists (select 1 from prtx2 -> Seq Scan on prtx1_1 Filter: ((a < 20) AND (c = 91)) -> Bitmap Heap Scan on prtx2_1 - Recheck Cond: ((b = (prtx1_1.b + 1)) OR (c = 99)) + Recheck Cond: ((c = 99) OR (b = (prtx1_1.b + 1))) Filter: (a = prtx1_1.a) -> BitmapOr - -> Bitmap Index Scan on prtx2_1_b_idx - Index Cond: (b = (prtx1_1.b + 1)) -> Bitmap Index Scan on prtx2_1_c_idx Index Cond: (c = 99) + -> Bitmap Index Scan on prtx2_1_b_idx + Index Cond: (b = (prtx1_1.b + 1)) -> Nested Loop Anti Join -> Seq Scan on prtx1_2 Filter: ((a < 20) AND (c = 91)) -> Bitmap Heap Scan on prtx2_2 - Recheck Cond: ((b = (prtx1_2.b + 1)) OR (c = 99)) + Recheck Cond: ((c = 99) OR (b = (prtx1_2.b + 1))) Filter: (a = prtx1_2.a) -> BitmapOr - -> Bitmap Index Scan on prtx2_2_b_idx - Index Cond: (b = (prtx1_2.b + 1)) -> Bitmap Index Scan on prtx2_2_c_idx Index Cond: (c = 99) + -> Bitmap Index Scan on prtx2_2_b_idx + Index Cond: (b = (prtx1_2.b + 1)) (23 rows) select * from prtx1 diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql index 068c66b95a5..be570da08a0 100644 --- a/src/test/regress/sql/create_index.sql +++ b/src/test/regress/sql/create_index.sql @@ -782,6 +782,12 @@ SELECT * FROM tenk1 WHERE tenthous = 1::numeric OR tenthous = 3::int4 OR tenthous = 42::numeric; EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 t1 + WHERE t1.thousand = 42 OR t1.thousand = (SELECT t2.tenthous FROM tenk1 t2 WHERE t2.thousand = t1.tenthous + 1 LIMIT 1); +SELECT count(*) FROM tenk1 t1 + WHERE t1.thousand = 42 OR t1.thousand = (SELECT t2.tenthous FROM tenk1 t2 WHERE t2.thousand = t1.tenthous + 1 LIMIT 1); + +EXPLAIN (COSTS OFF) SELECT count(*) FROM tenk1 WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); SELECT count(*) FROM tenk1 @@ -1367,6 +1373,9 @@ CREATE STATISTICS t_a_b_stat (mcv) ON a, b FROM bitmap_split_or; CREATE STATISTICS t_b_c_stat (mcv) ON b, c FROM bitmap_split_or; ANALYZE bitmap_split_or; EXPLAIN (COSTS OFF) +SELECT * FROM bitmap_split_or t1, bitmap_split_or t2 +WHERE t1.a = t2.b OR t1.a = 2; +EXPLAIN (COSTS OFF) SELECT * FROM bitmap_split_or WHERE a = 1 AND (b = 1 OR b = 2) AND c = 2; DROP TABLE bitmap_split_or; diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index 779d56cb30f..c7349eab933 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -3016,7 +3016,6 @@ SELECT t1.a FROM skip_fetch t1 LEFT JOIN skip_fetch t2 ON t2.a = 1 WHERE t2.a IS RESET enable_indexonlyscan; RESET enable_seqscan; - -- Test BitmapHeapScan with a rescan releases resources correctly SET enable_seqscan = off; SET enable_indexscan = off; @@ -3046,3 +3045,20 @@ SELECT 1 FROM group_tbl t1 GROUP BY s.c1, s.c2; DROP TABLE group_tbl; + +-- +-- Test for a nested loop join involving index scan, transforming OR-clauses +-- to SAOP. +-- + +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM tenk1 t1, tenk1 t2 +WHERE t2.thousand = t1.tenthous OR t2.thousand = t1.unique1 OR t2.thousand = t1.unique2; +SELECT COUNT(*) FROM tenk1 t1, tenk1 t2 +WHERE t2.thousand = t1.tenthous OR t2.thousand = t1.unique1 OR t2.thousand = t1.unique2; + +EXPLAIN (COSTS OFF) +SELECT COUNT(*) FROM onek t1 LEFT JOIN tenk1 t2 + ON (t2.thousand = t1.tenthous OR t2.thousand = t1.thousand); +SELECT COUNT(*) FROM onek t1 LEFT JOIN tenk1 t2 + ON (t2.thousand = t1.tenthous OR t2.thousand = t1.thousand); |
