mirror of
https://github.com/postgres/postgres.git
synced 2025-07-07 00:36:50 +03:00
Refactor the representation of indexable clauses in IndexPaths.
In place of three separate but interrelated lists (indexclauses, indexquals, and indexqualcols), an IndexPath now has one list "indexclauses" of IndexClause nodes. This holds basically the same information as before, but in a more useful format: in particular, there is now a clear connection between an indexclause (an original restriction clause from WHERE or JOIN/ON) and the indexquals (directly usable index conditions) derived from it. We also change the ground rules a bit by mandating that clause commutation, if needed, be done up-front so that what is stored in the indexquals list is always directly usable as an index condition. This gets rid of repeated re-determination of which side of the clause is the indexkey during costing and plan generation, as well as repeated lookups of the commutator operator. To minimize the added up-front cost, the typical case of commuting a plain OpExpr is handled by a new special-purpose function commute_restrictinfo(). For RowCompareExprs, generating the new clause properly commuted to begin with is not really any more complex than before, it's just different --- and we can save doing that work twice, as the pretty-klugy original implementation did. Tracking the connection between original and derived clauses lets us also track explicitly whether the derived clauses are an exact or lossy translation of the original. This provides a cheap solution to getting rid of unnecessary rechecks of boolean index clauses, which previously seemed like it'd be more expensive than it was worth. Another pleasant (IMO) side-effect is that EXPLAIN now always shows index clauses with the indexkey on the left; this seems less confusing. This commit leaves expand_indexqual_conditions() and some related functions in a slightly messy state. I didn't bother to change them any more than minimally necessary to work with the new data structure, because all that code is going to be refactored out of existence in a follow-on patch. Discussion: https://postgr.es/m/22182.1549124950@sss.pgh.pa.us
This commit is contained in:
@ -1504,7 +1504,7 @@ SELECT count(*) FROM quad_point_tbl WHERE box '(200,200,1000,1000)' @> p;
|
||||
-> Bitmap Heap Scan on quad_point_tbl
|
||||
Recheck Cond: ('(1000,1000),(200,200)'::box @> p)
|
||||
-> Bitmap Index Scan on sp_quad_ind
|
||||
Index Cond: ('(1000,1000),(200,200)'::box @> p)
|
||||
Index Cond: (p <@ '(1000,1000),(200,200)'::box)
|
||||
(5 rows)
|
||||
|
||||
SELECT count(*) FROM quad_point_tbl WHERE box '(200,200,1000,1000)' @> p;
|
||||
@ -1623,7 +1623,7 @@ SELECT count(*) FROM kd_point_tbl WHERE box '(200,200,1000,1000)' @> p;
|
||||
-> Bitmap Heap Scan on kd_point_tbl
|
||||
Recheck Cond: ('(1000,1000),(200,200)'::box @> p)
|
||||
-> Bitmap Index Scan on sp_kd_ind
|
||||
Index Cond: ('(1000,1000),(200,200)'::box @> p)
|
||||
Index Cond: (p <@ '(1000,1000),(200,200)'::box)
|
||||
(5 rows)
|
||||
|
||||
SELECT count(*) FROM kd_point_tbl WHERE box '(200,200,1000,1000)' @> p;
|
||||
@ -3181,8 +3181,7 @@ explain (costs off)
|
||||
Limit
|
||||
-> Index Scan using boolindex_b_i_key on boolindex
|
||||
Index Cond: (b = true)
|
||||
Filter: b
|
||||
(4 rows)
|
||||
(3 rows)
|
||||
|
||||
explain (costs off)
|
||||
select * from boolindex where b = true order by i desc limit 10;
|
||||
@ -3191,8 +3190,7 @@ explain (costs off)
|
||||
Limit
|
||||
-> Index Scan Backward using boolindex_b_i_key on boolindex
|
||||
Index Cond: (b = true)
|
||||
Filter: b
|
||||
(4 rows)
|
||||
(3 rows)
|
||||
|
||||
explain (costs off)
|
||||
select * from boolindex where not b order by i limit 10;
|
||||
@ -3201,8 +3199,7 @@ explain (costs off)
|
||||
Limit
|
||||
-> Index Scan using boolindex_b_i_key on boolindex
|
||||
Index Cond: (b = false)
|
||||
Filter: (NOT b)
|
||||
(4 rows)
|
||||
(3 rows)
|
||||
|
||||
--
|
||||
-- Test for multilevel page deletion
|
||||
|
@ -3078,9 +3078,9 @@ where q1 = thousand or q2 = thousand;
|
||||
Recheck Cond: ((q1.q1 = thousand) OR (q2.q2 = thousand))
|
||||
-> BitmapOr
|
||||
-> Bitmap Index Scan on tenk1_thous_tenthous
|
||||
Index Cond: (q1.q1 = thousand)
|
||||
Index Cond: (thousand = q1.q1)
|
||||
-> Bitmap Index Scan on tenk1_thous_tenthous
|
||||
Index Cond: (q2.q2 = thousand)
|
||||
Index Cond: (thousand = q2.q2)
|
||||
-> Hash
|
||||
-> Seq Scan on int4_tbl
|
||||
(15 rows)
|
||||
@ -3332,7 +3332,7 @@ where t1.unique1 = 1;
|
||||
-> Bitmap Heap Scan on tenk1 t2
|
||||
Recheck Cond: (t1.hundred = hundred)
|
||||
-> Bitmap Index Scan on tenk1_hundred
|
||||
Index Cond: (t1.hundred = hundred)
|
||||
Index Cond: (hundred = t1.hundred)
|
||||
-> Index Scan using tenk1_unique2 on tenk1 t3
|
||||
Index Cond: (unique2 = t2.thousand)
|
||||
(11 rows)
|
||||
@ -3352,7 +3352,7 @@ where t1.unique1 = 1;
|
||||
-> Bitmap Heap Scan on tenk1 t2
|
||||
Recheck Cond: (t1.hundred = hundred)
|
||||
-> Bitmap Index Scan on tenk1_hundred
|
||||
Index Cond: (t1.hundred = hundred)
|
||||
Index Cond: (hundred = t1.hundred)
|
||||
-> Index Scan using tenk1_unique2 on tenk1 t3
|
||||
Index Cond: (unique2 = t2.thousand)
|
||||
(11 rows)
|
||||
@ -3408,7 +3408,7 @@ select b.unique1 from
|
||||
-> Nested Loop
|
||||
-> Seq Scan on int4_tbl i1
|
||||
-> Index Scan using tenk1_thous_tenthous on tenk1 b
|
||||
Index Cond: ((thousand = i1.f1) AND (i2.f1 = tenthous))
|
||||
Index Cond: ((thousand = i1.f1) AND (tenthous = i2.f1))
|
||||
-> Index Scan using tenk1_unique1 on tenk1 a
|
||||
Index Cond: (unique1 = b.unique2)
|
||||
-> Index Only Scan using tenk1_thous_tenthous on tenk1 c
|
||||
@ -3444,7 +3444,7 @@ order by fault;
|
||||
Filter: ((COALESCE(tenk1.unique1, '-1'::integer) + int8_tbl.q1) = 122)
|
||||
-> Seq Scan on int8_tbl
|
||||
-> Index Scan using tenk1_unique2 on tenk1
|
||||
Index Cond: (int8_tbl.q2 = unique2)
|
||||
Index Cond: (unique2 = int8_tbl.q2)
|
||||
(5 rows)
|
||||
|
||||
select * from
|
||||
@ -3499,7 +3499,7 @@ select q1, unique2, thousand, hundred
|
||||
Filter: ((COALESCE(b.thousand, 123) = a.q1) AND (a.q1 = COALESCE(b.hundred, 123)))
|
||||
-> Seq Scan on int8_tbl a
|
||||
-> Index Scan using tenk1_unique2 on tenk1 b
|
||||
Index Cond: (a.q1 = unique2)
|
||||
Index Cond: (unique2 = a.q1)
|
||||
(5 rows)
|
||||
|
||||
select q1, unique2, thousand, hundred
|
||||
@ -4586,7 +4586,7 @@ explain (costs off)
|
||||
Nested Loop Left Join
|
||||
-> Seq Scan on int4_tbl x
|
||||
-> Index Scan using tenk1_unique1 on tenk1
|
||||
Index Cond: (x.f1 = unique1)
|
||||
Index Cond: (unique1 = x.f1)
|
||||
(4 rows)
|
||||
|
||||
-- check scoping of lateral versus parent references
|
||||
|
@ -647,7 +647,7 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2
|
||||
-> Seq Scan on prt1_e_p1 t3
|
||||
Filter: (c = 0)
|
||||
-> Index Scan using iprt2_p1_b on prt2_p1 t2
|
||||
Index Cond: (t1.a = b)
|
||||
Index Cond: (b = t1.a)
|
||||
-> Nested Loop Left Join
|
||||
-> Hash Right Join
|
||||
Hash Cond: (t1_1.a = ((t3_1.a + t3_1.b) / 2))
|
||||
@ -656,7 +656,7 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2
|
||||
-> Seq Scan on prt1_e_p2 t3_1
|
||||
Filter: (c = 0)
|
||||
-> Index Scan using iprt2_p2_b on prt2_p2 t2_1
|
||||
Index Cond: (t1_1.a = b)
|
||||
Index Cond: (b = t1_1.a)
|
||||
-> Nested Loop Left Join
|
||||
-> Hash Right Join
|
||||
Hash Cond: (t1_2.a = ((t3_2.a + t3_2.b) / 2))
|
||||
@ -665,7 +665,7 @@ SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2
|
||||
-> Seq Scan on prt1_e_p3 t3_2
|
||||
Filter: (c = 0)
|
||||
-> Index Scan using iprt2_p3_b on prt2_p3 t2_2
|
||||
Index Cond: (t1_2.a = b)
|
||||
Index Cond: (b = t1_2.a)
|
||||
(30 rows)
|
||||
|
||||
SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFT JOIN prt2 t2 ON t1.a = t2.b) RIGHT JOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.c = 0 ORDER BY t1.a, t2.b, t3.a + t3.b;
|
||||
@ -1878,11 +1878,11 @@ SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFT JOIN prt2 t2 ON (t1.a < t2.b);
|
||||
-> Seq Scan on prt1_p3 t1_2
|
||||
-> Append
|
||||
-> Index Scan using iprt2_p1_b on prt2_p1 t2
|
||||
Index Cond: (t1.a < b)
|
||||
Index Cond: (b > t1.a)
|
||||
-> Index Scan using iprt2_p2_b on prt2_p2 t2_1
|
||||
Index Cond: (t1.a < b)
|
||||
Index Cond: (b > t1.a)
|
||||
-> Index Scan using iprt2_p3_b on prt2_p3 t2_2
|
||||
Index Cond: (t1.a < b)
|
||||
Index Cond: (b > t1.a)
|
||||
(12 rows)
|
||||
|
||||
-- equi-join with join condition on partial keys does not qualify for
|
||||
|
@ -2635,17 +2635,17 @@ select * from tbl1 join tprt on tbl1.col1 > tprt.col1;
|
||||
-> Seq Scan on tbl1 (actual rows=2 loops=1)
|
||||
-> Append (actual rows=3 loops=2)
|
||||
-> Index Scan using tprt1_idx on tprt_1 (actual rows=2 loops=2)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
-> Index Scan using tprt2_idx on tprt_2 (actual rows=2 loops=1)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
-> Index Scan using tprt3_idx on tprt_3 (never executed)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
-> Index Scan using tprt4_idx on tprt_4 (never executed)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
-> Index Scan using tprt5_idx on tprt_5 (never executed)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
-> Index Scan using tprt6_idx on tprt_6 (never executed)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
(15 rows)
|
||||
|
||||
explain (analyze, costs off, summary off, timing off)
|
||||
@ -2701,17 +2701,17 @@ select * from tbl1 inner join tprt on tbl1.col1 > tprt.col1;
|
||||
-> Seq Scan on tbl1 (actual rows=5 loops=1)
|
||||
-> Append (actual rows=5 loops=5)
|
||||
-> Index Scan using tprt1_idx on tprt_1 (actual rows=2 loops=5)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
-> Index Scan using tprt2_idx on tprt_2 (actual rows=3 loops=4)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
-> Index Scan using tprt3_idx on tprt_3 (actual rows=1 loops=2)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
-> Index Scan using tprt4_idx on tprt_4 (never executed)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
-> Index Scan using tprt5_idx on tprt_5 (never executed)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
-> Index Scan using tprt6_idx on tprt_6 (never executed)
|
||||
Index Cond: (tbl1.col1 > col1)
|
||||
Index Cond: (col1 < tbl1.col1)
|
||||
(15 rows)
|
||||
|
||||
explain (analyze, costs off, summary off, timing off)
|
||||
@ -2786,17 +2786,17 @@ select * from tbl1 join tprt on tbl1.col1 < tprt.col1;
|
||||
-> Seq Scan on tbl1 (actual rows=1 loops=1)
|
||||
-> Append (actual rows=1 loops=1)
|
||||
-> Index Scan using tprt1_idx on tprt_1 (never executed)
|
||||
Index Cond: (tbl1.col1 < col1)
|
||||
Index Cond: (col1 > tbl1.col1)
|
||||
-> Index Scan using tprt2_idx on tprt_2 (never executed)
|
||||
Index Cond: (tbl1.col1 < col1)
|
||||
Index Cond: (col1 > tbl1.col1)
|
||||
-> Index Scan using tprt3_idx on tprt_3 (never executed)
|
||||
Index Cond: (tbl1.col1 < col1)
|
||||
Index Cond: (col1 > tbl1.col1)
|
||||
-> Index Scan using tprt4_idx on tprt_4 (never executed)
|
||||
Index Cond: (tbl1.col1 < col1)
|
||||
Index Cond: (col1 > tbl1.col1)
|
||||
-> Index Scan using tprt5_idx on tprt_5 (never executed)
|
||||
Index Cond: (tbl1.col1 < col1)
|
||||
Index Cond: (col1 > tbl1.col1)
|
||||
-> Index Scan using tprt6_idx on tprt_6 (actual rows=1 loops=1)
|
||||
Index Cond: (tbl1.col1 < col1)
|
||||
Index Cond: (col1 > tbl1.col1)
|
||||
(15 rows)
|
||||
|
||||
select tbl1.col1, tprt.col1 from tbl1
|
||||
|
Reference in New Issue
Block a user