1
0
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:
Tom Lane
2019-02-09 17:30:43 -05:00
parent 6401583863
commit 1a8d5afb0d
22 changed files with 704 additions and 628 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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