-- -- PARTITION_JOIN -- Test partitionwise join between partitioned tables --
-- Enable partitionwise join, which by default is disabled. SET enable_partitionwise_join totrue;
-- -- partitioned by a single column -- CREATETABLE prt1 (a int, b int, c varchar) PARTITION BY RANGE(a); CREATETABLE prt1_p1 PARTITION OF prt1 FORVALUESFROM (0) TO (250); CREATETABLE prt1_p3 PARTITION OF prt1 FORVALUESFROM (500) TO (600); CREATETABLE prt1_p2 PARTITION OF prt1 FORVALUESFROM (250) TO (500); INSERTINTO prt1 SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(0, 599) i WHERE i % 2 = 0; CREATEINDEX iprt1_p1_a on prt1_p1(a); CREATEINDEX iprt1_p2_a on prt1_p2(a); CREATEINDEX iprt1_p3_a on prt1_p3(a); ANALYZE prt1;
CREATETABLE prt2 (a int, b int, c varchar) PARTITION BY RANGE(b); CREATETABLE prt2_p1 PARTITION OF prt2 FORVALUESFROM (0) TO (250); CREATETABLE prt2_p2 PARTITION OF prt2 FORVALUESFROM (250) TO (500); CREATETABLE prt2_p3 PARTITION OF prt2 FORVALUESFROM (500) TO (600); INSERTINTO prt2 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(0, 599) i WHERE i % 3 = 0; CREATEINDEX iprt2_p1_b on prt2_p1(b); CREATEINDEX iprt2_p2_b on prt2_p2(b); CREATEINDEX iprt2_p3_b on prt2_p3(b); ANALYZE prt2;
-- inner join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.b = 0ORDERBY t1.a, t2.b;
-- inner join with partially-redundant join clauses EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.a AND t1.a = t2.b ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.a AND t1.a = t2.b ORDERBY t1.a, t2.b;
-- left outer join, 3-way EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM prt1 t1 LEFTJOIN prt1 t2 ON t1.a = t2.a LEFTJOIN prt1 t3 ON t2.a = t3.a; SELECT COUNT(*) FROM prt1 t1 LEFTJOIN prt1 t2 ON t1.a = t2.a LEFTJOIN prt1 t3 ON t2.a = t3.a;
-- left outer join, with whole-row reference; partitionwise join does not apply EXPLAIN (COSTS OFF) SELECT t1, t2 FROM prt1 t1 LEFTJOIN prt2 t2 ON t1.a = t2.b WHERE t1.b = 0ORDERBY t1.a, t2.b; SELECT t1, t2 FROM prt1 t1 LEFTJOIN prt2 t2 ON t1.a = t2.b WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- right outer join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHTJOIN prt2 t2 ON t1.a = t2.b WHERE t2.a = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 RIGHTJOIN prt2 t2 ON t1.a = t2.b WHERE t2.a = 0ORDERBY t1.a, t2.b;
-- full outer join, with placeholder vars EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT50 phv, * FROM prt1 WHERE prt1.b = 0) t1 FULL JOIN (SELECT75 phv, * FROM prt2 WHERE prt2.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT50 phv, * FROM prt1 WHERE prt1.b = 0) t1 FULL JOIN (SELECT75 phv, * FROM prt2 WHERE prt2.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDERBY t1.a, t2.b;
-- Join with pruned partitions from joining relations EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a < 450AND t2.b > 250AND t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a < 450AND t2.b > 250AND t1.b = 0ORDERBY t1.a, t2.b;
-- Currently we can't do partitioned join if nullable-side partitions are pruned EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFTJOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFTJOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- Currently we can't do partitioned join if nullable-side partitions are pruned EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0OR t2.a = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a < 450) t1 FULL JOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0OR t2.a = 0ORDERBY t1.a, t2.b;
-- Semi-join EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t2.b FROM prt2 t2 WHERE t2.a = 0) AND t1.b = 0ORDERBYt1.a; SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t2.b FROM prt2 t2 WHERE t2.a = 0) AND t1.b = 0ORDERBYt1.a;
-- Anti-join with aggregates EXPLAIN (COSTS OFF) SELECT sum(t1.a), avg(t1.a), sum(t1.b), avg(t1.b) FROM prt1 t1 WHERENOTEXISTS (SELECT1FROM prt2 t2 WHERE t1.a = t2.b); SELECT sum(t1.a), avg(t1.a), sum(t1.b), avg(t1.b) FROM prt1 t1 WHERENOTEXISTS (SELECT1FROM prt2 t2 WHERE t1.a = t2.b);
-- lateral reference EXPLAIN (COSTS OFF) SELECT * FROM prt1 t1 LEFTJOIN LATERAL
(SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.b) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss ON t1.a = ss.t2a WHERE t1.b = 0ORDERBY t1.a; SELECT * FROM prt1 t1 LEFTJOIN LATERAL
(SELECT t2.a AS t2a, t3.a AS t3a, least(t1.a,t2.a,t3.b) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss ON t1.a = ss.t2a WHERE t1.b = 0ORDERBY t1.a;
EXPLAIN (COSTS OFF) SELECT t1.a, ss.t2a, ss.t2c FROM prt1 t1 LEFTJOIN LATERAL
(SELECT t2.a AS t2a, t3.a AS t3a, t2.b t2b, t2.c t2c, least(t1.a,t2.a,t3.b) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss ON t1.c = ss.t2c WHERE (t1.b + coalesce(ss.t2b, 0)) = 0ORDERBY t1.a; SELECT t1.a, ss.t2a, ss.t2c FROM prt1 t1 LEFTJOIN LATERAL
(SELECT t2.a AS t2a, t3.a AS t3a, t2.b t2b, t2.c t2c, least(t1.a,t2.a,t3.a) FROM prt1 t2 JOIN prt2 t3 ON (t2.a = t3.b)) ss ON t1.c = ss.t2c WHERE (t1.b + coalesce(ss.t2b, 0)) = 0ORDERBY t1.a;
-- lateral reference in sample scan EXPLAIN (COSTS OFF) SELECT * FROM prt1 t1 JOIN LATERAL
(SELECT * FROM prt1 t2 TABLESAMPLE SYSTEM (t1.a) REPEATABLE(t1.b)) s ON t1.a = s.a;
-- lateral reference in scan's restriction clauses EXPLAIN (COSTS OFF) SELECT count(*) FROM prt1 t1 LEFTJOIN LATERAL
(SELECT t1.b AS t1b, t2.* FROM prt2 t2) s ON t1.a = s.b WHERE s.t1b = s.a; SELECT count(*) FROM prt1 t1 LEFTJOIN LATERAL
(SELECT t1.b AS t1b, t2.* FROM prt2 t2) s ON t1.a = s.b WHERE s.t1b = s.a;
EXPLAIN (COSTS OFF) SELECT count(*) FROM prt1 t1 LEFTJOIN LATERAL
(SELECT t1.b AS t1b, t2.* FROM prt2 t2) s ON t1.a = s.b WHERE s.t1b = s.b; SELECT count(*) FROM prt1 t1 LEFTJOIN LATERAL
(SELECT t1.b AS t1b, t2.* FROM prt2 t2) s ON t1.a = s.b WHERE s.t1b = s.b;
-- bug with inadequate sort key representation SET enable_partitionwise_aggregate TOtrue; SET enable_hashjoin TOfalse;
EXPLAIN (COSTS OFF) SELECT a, b FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) WHERE a BETWEEN490AND510 GROUPBY1, 2ORDERBY1, 2; SELECT a, b FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) WHERE a BETWEEN490AND510 GROUPBY1, 2ORDERBY1, 2;
-- bug in freeing the SpecialJoinInfo of a child-join EXPLAIN (COSTS OFF) SELECT * FROM prt1 t1 JOIN prt1 t2 ON t1.a = t2.a WHERE t1.a IN (SELECT a FROM prt1 t3);
-- -- partitioned by expression -- CREATETABLE prt1_e (a int, b int, c int) PARTITION BY RANGE(((a + b)/2)); CREATETABLE prt1_e_p1 PARTITION OF prt1_e FORVALUESFROM (0) TO (250); CREATETABLE prt1_e_p2 PARTITION OF prt1_e FORVALUESFROM (250) TO (500); CREATETABLE prt1_e_p3 PARTITION OF prt1_e FORVALUESFROM (500) TO (600); INSERTINTO prt1_e SELECT i, i, i % 25FROM generate_series(0, 599, 2) i; CREATEINDEX iprt1_e_p1_ab2 on prt1_e_p1(((a+b)/2)); CREATEINDEX iprt1_e_p2_ab2 on prt1_e_p2(((a+b)/2)); CREATEINDEX iprt1_e_p3_ab2 on prt1_e_p3(((a+b)/2)); ANALYZE prt1_e;
CREATETABLE prt2_e (a int, b int, c int) PARTITION BY RANGE(((b + a)/2)); CREATETABLE prt2_e_p1 PARTITION OF prt2_e FORVALUESFROM (0) TO (250); CREATETABLE prt2_e_p2 PARTITION OF prt2_e FORVALUESFROM (250) TO (500); CREATETABLE prt2_e_p3 PARTITION OF prt2_e FORVALUESFROM (500) TO (600); INSERTINTO prt2_e SELECT i, i, i % 25FROM generate_series(0, 599, 3) i; ANALYZE prt2_e;
-- -- N-way join -- EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2AND t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM prt1 t1, prt2 t2, prt1_e t3 WHERE t1.a = t2.b AND t1.a = (t3.a + t3.b)/2AND t1.b = 0ORDERBY t1.a, t2.b;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFTJOIN prt2 t2 ON t1.a = t2.b) LEFTJOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.b = 0ORDERBY t1.a, t2.b, t3.a + t3.b; SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFTJOIN prt2 t2 ON t1.a = t2.b) LEFTJOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.b = 0ORDERBY t1.a, t2.b, t3.a + t3.b;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFTJOIN prt2 t2 ON t1.a = t2.b) RIGHTJOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.c = 0ORDERBY t1.a, t2.b, t3.a + t3.b; SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFTJOIN prt2 t2 ON t1.a = t2.b) RIGHTJOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.c = 0ORDERBY t1.a, t2.b, t3.a + t3.b;
-- -- 3-way full join -- EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) FULL JOIN prt2 p3(b,a,c) USING (a, b) WHERE a BETWEEN490AND510; SELECT COUNT(*) FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) FULL JOIN prt2 p3(b,a,c) USING (a, b) WHERE a BETWEEN490AND510;
-- -- 4-way full join -- EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) FULL JOIN prt2 p3(b,a,c) USING (a, b) FULL JOIN prt1 p4 (a,b,c) USING (a, b) WHERE a BETWEEN490AND510; SELECT COUNT(*) FROM prt1 FULL JOIN prt2 p2(b,a,c) USING(a,b) FULL JOIN prt2 p3(b,a,c) USING (a, b) FULL JOIN prt1 p4 (a,b,c) USING (a, b) WHERE a BETWEEN490AND510;
-- Cases with non-nullable expressions in subquery results; -- make sure these go to null as expected EXPLAIN (COSTS OFF) SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT50 phv, * FROM prt1 WHERE prt1.b = 0) t1 FULL JOIN (SELECT75 phv, * FROM prt2 WHERE prt2.a = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT50 phv, * FROM prt1_e WHERE prt1_e.c = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDERBY t1.a, t2.b, t3.a + t3.b; SELECT t1.a, t1.phv, t2.b, t2.phv, t3.a + t3.b, t3.phv FROM ((SELECT50 phv, * FROM prt1 WHERE prt1.b = 0) t1 FULL JOIN (SELECT75 phv, * FROM prt2 WHERE prt2.a = 0) t2 ON (t1.a = t2.b)) FULL JOIN (SELECT50 phv, * FROM prt1_e WHERE prt1_e.c = 0) t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t1.a = t1.phv OR t2.b = t2.phv OR (t3.a + t3.b)/2 = t3.phv ORDERBY t1.a, t2.b, t3.a + t3.b;
-- Semi-join EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.a = 0AND t1.b = (t2.a + t2.b)/2) AND t1.b = 0ORDERBY t1.a; SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1, prt1_e t2 WHERE t1.a = 0AND t1.b = (t2.a + t2.b)/2) AND t1.b = 0ORDERBY t1.a;
EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2FROM prt1_e t1 WHERE t1.c = 0)) AND t1.b = 0ORDERBY t1.a; SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2FROM prt1_e t1 WHERE t1.c = 0)) AND t1.b = 0ORDERBY t1.a;
-- test merge joins SET enable_hashjoin TO off; SET enable_nestloop TO off;
EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2FROM prt1_e t1 WHERE t1.c = 0)) AND t1.b = 0ORDERBY t1.a; SELECT t1.* FROM prt1 t1 WHERE t1.a IN (SELECT t1.b FROM prt2 t1 WHERE t1.b IN (SELECT (t1.a + t1.b)/2FROM prt1_e t1 WHERE t1.c = 0)) AND t1.b = 0ORDERBY t1.a;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFTJOIN prt2 t2 ON t1.a = t2.b) RIGHTJOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.c = 0ORDERBY t1.a, t2.b, t3.a + t3.b; SELECT t1.a, t1.c, t2.b, t2.c, t3.a + t3.b, t3.c FROM (prt1 t1 LEFTJOIN prt2 t2 ON t1.a = t2.b) RIGHTJOIN prt1_e t3 ON (t1.a = (t3.a + t3.b)/2) WHERE t3.c = 0ORDERBY t1.a, t2.b, t3.a + t3.b;
-- MergeAppend on nullable column -- This should generate a partitionwise join, but currently fails to EXPLAIN (COSTS OFF) SELECT t1.a, t2.b FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFTJOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t2.b FROM (SELECT * FROM prt1 WHERE a < 450) t1 LEFTJOIN (SELECT * FROM prt2 WHERE b > 250) t2 ON t1.a = t2.b WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- merge join when expression with whole-row reference needs to be sorted; -- partitionwise join does not apply EXPLAIN (COSTS OFF) SELECT t1.a, t2.b FROM prt1 t1, prt2 t2 WHERE t1::text = t2::text AND t1.a = t2.b ORDERBY t1.a; SELECT t1.a, t2.b FROM prt1 t1, prt2 t2 WHERE t1::text = t2::text AND t1.a = t2.b ORDERBY t1.a;
RESET enable_hashjoin;
RESET enable_nestloop;
-- -- partitioned by multiple columns -- CREATETABLE prt1_m (a int, b int, c int) PARTITION BY RANGE(a, ((a + b)/2)); CREATETABLE prt1_m_p1 PARTITION OF prt1_m FORVALUESFROM (0, 0) TO (250, 250); CREATETABLE prt1_m_p2 PARTITION OF prt1_m FORVALUESFROM (250, 250) TO (500, 500); CREATETABLE prt1_m_p3 PARTITION OF prt1_m FORVALUESFROM (500, 500) TO (600, 600); INSERTINTO prt1_m SELECT i, i, i % 25FROM generate_series(0, 599, 2) i; ANALYZE prt1_m;
CREATETABLE prt2_m (a int, b int, c int) PARTITION BY RANGE(((b + a)/2), b); CREATETABLE prt2_m_p1 PARTITION OF prt2_m FORVALUESFROM (0, 0) TO (250, 250); CREATETABLE prt2_m_p2 PARTITION OF prt2_m FORVALUESFROM (250, 250) TO (500, 500); CREATETABLE prt2_m_p3 PARTITION OF prt2_m FORVALUESFROM (500, 500) TO (600, 600); INSERTINTO prt2_m SELECT i, i, i % 25FROM generate_series(0, 599, 3) i; ANALYZE prt2_m;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.c = 0) t1 FULL JOIN (SELECT* FROM prt2_m WHERE prt2_m.c = 0) t2 ON (t1.a = (t2.b + t2.a)/2AND t2.b = (t1.a + t1.b)/2) ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_m WHERE prt1_m.c = 0) t1 FULL JOIN (SELECT* FROM prt2_m WHERE prt2_m.c = 0) t2 ON (t1.a = (t2.b + t2.a)/2AND t2.b = (t1.a + t1.b)/2) ORDERBY t1.a, t2.b;
-- -- tests for list partitioned tables. -- CREATETABLE plt1 (a int, b int, c text) PARTITION BY LIST(c); CREATETABLE plt1_p1 PARTITION OF plt1 FORVALUESIN ('0000', '0003', '0004', '0010'); CREATETABLE plt1_p2 PARTITION OF plt1 FORVALUESIN ('0001', '0005', '0002', '0009'); CREATETABLE plt1_p3 PARTITION OF plt1 FORVALUESIN ('0006', '0007', '0008', '0011'); INSERTINTO plt1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; ANALYZE plt1;
CREATETABLE plt2 (a int, b int, c text) PARTITION BY LIST(c); CREATETABLE plt2_p1 PARTITION OF plt2 FORVALUESIN ('0000', '0003', '0004', '0010'); CREATETABLE plt2_p2 PARTITION OF plt2 FORVALUESIN ('0001', '0005', '0002', '0009'); CREATETABLE plt2_p3 PARTITION OF plt2 FORVALUESIN ('0006', '0007', '0008', '0011'); INSERTINTO plt2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 3) i; ANALYZE plt2;
-- -- list partitioned by expression -- CREATETABLE plt1_e (a int, b int, c text) PARTITION BY LIST(ltrim(c, 'A')); CREATETABLE plt1_e_p1 PARTITION OF plt1_e FORVALUESIN ('0000', '0003', '0004', '0010'); CREATETABLE plt1_e_p2 PARTITION OF plt1_e FORVALUESIN ('0001', '0005', '0002', '0009'); CREATETABLE plt1_e_p3 PARTITION OF plt1_e FORVALUESIN ('0006', '0007', '0008', '0011'); INSERTINTO plt1_e SELECT i, i, 'A' || to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; ANALYZE plt1_e;
-- test partition matching with N-way join EXPLAIN (COSTS OFF) SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.b = t2.b AND t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUPBY t1.c, t2.c, t3.c ORDERBY t1.c, t2.c, t3.c; SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM plt1 t1, plt2 t2, plt1_e t3 WHERE t1.b = t2.b AND t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUPBY t1.c, t2.c, t3.c ORDERBY t1.c, t2.c, t3.c;
-- joins where one of the relations is proven empty EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt2 t2 WHERE t1.a = t2.b AND t1.a = 1AND t1.a = 2;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1AND a = 2) t1 LEFTJOIN prt2 t2 ON t1.a = t2.b;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1AND a = 2) t1 RIGHTJOIN prt2 t2 ON t1.a = t2.b, prt1 t3 WHERE t2.b = t3.a;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1 WHERE a = 1AND a = 2) t1 FULL JOIN prt2 t2 ON t1.a = t2.b WHERE t2.a = 0ORDERBY t1.a, t2.b;
-- -- tests for hash partitioned tables. -- CREATETABLE pht1 (a int, b int, c text) PARTITION BY HASH(c); CREATETABLE pht1_p1 PARTITION OF pht1 FORVALUESWITH (MODULUS 3, REMAINDER 0); CREATETABLE pht1_p2 PARTITION OF pht1 FORVALUESWITH (MODULUS 3, REMAINDER 1); CREATETABLE pht1_p3 PARTITION OF pht1 FORVALUESWITH (MODULUS 3, REMAINDER 2); INSERTINTO pht1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; ANALYZE pht1;
CREATETABLE pht2 (a int, b int, c text) PARTITION BY HASH(c); CREATETABLE pht2_p1 PARTITION OF pht2 FORVALUESWITH (MODULUS 3, REMAINDER 0); CREATETABLE pht2_p2 PARTITION OF pht2 FORVALUESWITH (MODULUS 3, REMAINDER 1); CREATETABLE pht2_p3 PARTITION OF pht2 FORVALUESWITH (MODULUS 3, REMAINDER 2); INSERTINTO pht2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 3) i; ANALYZE pht2;
-- -- hash partitioned by expression -- CREATETABLE pht1_e (a int, b int, c text) PARTITION BY HASH(ltrim(c, 'A')); CREATETABLE pht1_e_p1 PARTITION OF pht1_e FORVALUESWITH (MODULUS 3, REMAINDER 0); CREATETABLE pht1_e_p2 PARTITION OF pht1_e FORVALUESWITH (MODULUS 3, REMAINDER 1); CREATETABLE pht1_e_p3 PARTITION OF pht1_e FORVALUESWITH (MODULUS 3, REMAINDER 2); INSERTINTO pht1_e SELECT i, i, 'A' || to_char(i/50, 'FM0000') FROM generate_series(0, 299, 2) i; ANALYZE pht1_e;
-- test partition matching with N-way join EXPLAIN (COSTS OFF) SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM pht1 t1, pht2 t2, pht1_e t3 WHERE t1.b = t2.b AND t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUPBY t1.c, t2.c, t3.c ORDERBY t1.c, t2.c, t3.c; SELECT avg(t1.a), avg(t2.b), avg(t3.a + t3.b), t1.c, t2.c, t3.c FROM pht1 t1, pht2 t2, pht1_e t3 WHERE t1.b = t2.b AND t1.c = t2.c AND ltrim(t3.c, 'A') = t1.c GROUPBY t1.c, t2.c, t3.c ORDERBY t1.c, t2.c, t3.c;
EXPLAIN (COSTS OFF) SELECT avg(t1.a), avg(t2.b), t1.c, t2.c FROM plt1 t1 RIGHTJOIN plt2 t2 ON t1.c = t2.c WHERE t1.a % 25 = 0GROUPBY t1.c, t2.c ORDERBY t1.c, t2.c; -- -- multiple levels of partitioning -- CREATETABLE prt1_l (a int, b int, c varchar) PARTITION BY RANGE(a); CREATETABLE prt1_l_p1 PARTITION OF prt1_l FORVALUESFROM (0) TO (250); CREATETABLE prt1_l_p2 PARTITION OF prt1_l FORVALUESFROM (250) TO (500) PARTITION BY LIST (c); CREATETABLE prt1_l_p2_p1 PARTITION OF prt1_l_p2 FORVALUESIN ('0000', '0001'); CREATETABLE prt1_l_p2_p2 PARTITION OF prt1_l_p2 FORVALUESIN ('0002', '0003'); CREATETABLE prt1_l_p3 PARTITION OF prt1_l FORVALUESFROM (500) TO (600) PARTITION BY RANGE (b); CREATETABLE prt1_l_p3_p1 PARTITION OF prt1_l_p3 FORVALUESFROM (0) TO (13); CREATETABLE prt1_l_p3_p2 PARTITION OF prt1_l_p3 FORVALUESFROM (13) TO (25); INSERTINTO prt1_l SELECT i, i % 25, to_char(i % 4, 'FM0000') FROM generate_series(0, 599, 2) i; ANALYZE prt1_l;
CREATETABLE prt2_l (a int, b int, c varchar) PARTITION BY RANGE(b); CREATETABLE prt2_l_p1 PARTITION OF prt2_l FORVALUESFROM (0) TO (250); CREATETABLE prt2_l_p2 PARTITION OF prt2_l FORVALUESFROM (250) TO (500) PARTITION BY LIST (c); CREATETABLE prt2_l_p2_p1 PARTITION OF prt2_l_p2 FORVALUESIN ('0000', '0001'); CREATETABLE prt2_l_p2_p2 PARTITION OF prt2_l_p2 FORVALUESIN ('0002', '0003'); CREATETABLE prt2_l_p3 PARTITION OF prt2_l FORVALUESFROM (500) TO (600) PARTITION BY RANGE (a); CREATETABLE prt2_l_p3_p1 PARTITION OF prt2_l_p3 FORVALUESFROM (0) TO (13); CREATETABLE prt2_l_p3_p2 PARTITION OF prt2_l_p3 FORVALUESFROM (13) TO (25); INSERTINTO prt2_l SELECT i % 25, i, to_char(i % 4, 'FM0000') FROM generate_series(0, 599, 3) i; ANALYZE prt2_l;
-- inner join, qual covering only top-level partitions EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.b AND t1.b = 0ORDERBY t1.a, t2.b;
-- inner join with partially-redundant join clauses EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.a AND t1.a = t2.b AND t1.c = t2.c ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1, prt2_l t2 WHERE t1.a = t2.a AND t1.a = t2.b AND t1.c = t2.c ORDERBY t1.a, t2.b;
-- left join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 LEFTJOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 LEFTJOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- right join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 RIGHTJOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t2.a = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_l t1 RIGHTJOIN prt2_l t2 ON t1.a = t2.b AND t1.c = t2.c WHERE t2.a = 0ORDERBY t1.a, t2.b;
-- full join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE prt1_l.b = 0) t1 FULL JOIN (SELECT* FROM prt2_l WHERE prt2_l.a = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c) ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE prt1_l.b = 0) t1 FULL JOIN (SELECT* FROM prt2_l WHERE prt2_l.a = 0) t2 ON (t1.a = t2.b AND t1.c = t2.c) ORDERBY t1.a, t2.b;
-- lateral partitionwise join EXPLAIN (COSTS OFF) SELECT * FROM prt1_l t1 LEFTJOIN LATERAL
(SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.b AS t3b, least(t1.a,t2.a,t3.b) FROM prt1_l t2 JOIN prt2_l t3 ON (t2.a = t3.b AND t2.c = t3.c)) ss ON t1.a = ss.t2a AND t1.c = ss.t2c WHERE t1.b = 0ORDERBY t1.a; SELECT * FROM prt1_l t1 LEFTJOIN LATERAL
(SELECT t2.a AS t2a, t2.c AS t2c, t2.b AS t2b, t3.b AS t3b, least(t1.a,t2.a,t3.b) FROM prt1_l t2 JOIN prt2_l t3 ON (t2.a = t3.b AND t2.c = t3.c)) ss ON t1.a = ss.t2a AND t1.c = ss.t2c WHERE t1.b = 0ORDERBY t1.a;
-- partitionwise join with lateral reference in sample scan EXPLAIN (COSTS OFF) SELECT * FROM prt1_l t1 JOIN LATERAL
(SELECT * FROM prt1_l t2 TABLESAMPLE SYSTEM (t1.a) REPEATABLE(t1.b)) s ON t1.a = s.a AND t1.b = s.b AND t1.c = s.c;
-- partitionwise join with lateral reference in scan's restriction clauses EXPLAIN (COSTS OFF) SELECT COUNT(*) FROM prt1_l t1 LEFTJOIN LATERAL
(SELECT t1.b AS t1b, t2.* FROM prt2_l t2) s ON t1.a = s.b AND t1.b = s.a AND t1.c = s.c WHERE s.t1b = s.a; SELECT COUNT(*) FROM prt1_l t1 LEFTJOIN LATERAL
(SELECT t1.b AS t1b, t2.* FROM prt2_l t2) s ON t1.a = s.b AND t1.b = s.a AND t1.c = s.c WHERE s.t1b = s.a;
-- join with one side empty EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT * FROM prt1_l WHERE a = 1AND a = 2) t1 RIGHTJOIN prt2_l t2 ON t1.a = t2.b AND t1.b = t2.a AND t1.c = t2.c;
-- Test case to verify proper handling of subqueries in a partitioned delete. -- The weird-looking lateral join is just there to force creation of a -- nestloop parameter within the subquery, which exposes the problem if the -- planner fails to make multiple copies of the subquery as appropriate. EXPLAIN (COSTS OFF) DELETEFROM prt1_l WHEREEXISTS ( SELECT1 FROM int4_tbl,
LATERAL (SELECT int4_tbl.f1 FROM int8_tbl LIMIT2) ss WHERE prt1_l.c ISNULL);
-- -- negative testcases -- CREATETABLE prt1_n (a int, b int, c varchar) PARTITION BY RANGE(c); CREATETABLE prt1_n_p1 PARTITION OF prt1_n FORVALUESFROM ('0000') TO ('0250'); CREATETABLE prt1_n_p2 PARTITION OF prt1_n FORVALUESFROM ('0250') TO ('0500'); INSERTINTO prt1_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 499, 2) i; ANALYZE prt1_n;
CREATETABLE prt2_n (a int, b int, c text) PARTITION BY LIST(c); CREATETABLE prt2_n_p1 PARTITION OF prt2_n FORVALUESIN ('0000', '0003', '0004', '0010', '0006', '0007'); CREATETABLE prt2_n_p2 PARTITION OF prt2_n FORVALUESIN ('0001', '0005', '0002', '0009', '0008', '0011'); INSERTINTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; ANALYZE prt2_n;
CREATETABLE prt3_n (a int, b int, c text) PARTITION BY LIST(c); CREATETABLE prt3_n_p1 PARTITION OF prt3_n FORVALUESIN ('0000', '0004', '0006', '0007'); CREATETABLE prt3_n_p2 PARTITION OF prt3_n FORVALUESIN ('0001', '0002', '0008', '0010'); CREATETABLE prt3_n_p3 PARTITION OF prt3_n FORVALUESIN ('0003', '0005', '0009', '0011'); INSERTINTO prt2_n SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 599, 2) i; ANALYZE prt3_n;
CREATETABLE prt4_n (a int, b int, c text) PARTITION BY RANGE(a); CREATETABLE prt4_n_p1 PARTITION OF prt4_n FORVALUESFROM (0) TO (300); CREATETABLE prt4_n_p2 PARTITION OF prt4_n FORVALUESFROM (300) TO (500); CREATETABLE prt4_n_p3 PARTITION OF prt4_n FORVALUESFROM (500) TO (600); INSERTINTO prt4_n SELECT i, i, to_char(i, 'FM0000') FROM generate_series(0, 599, 2) i; ANALYZE prt4_n;
-- partitionwise join can not be applied if the partition ranges differ EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2 WHERE t1.a = t2.a; EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1, prt4_n t2, prt2 t3 WHERE t1.a = t2.a and t1.a = t3.b;
-- partitionwise join can not be applied if there are no equi-join conditions -- between partition keys EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1 t1 LEFTJOIN prt2 t2 ON (t1.a < t2.b);
-- equi-join with join condition on partial keys does not qualify for -- partitionwise join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1, prt2_m t2 WHERE t1.a = (t2.b + t2.a)/2;
-- equi-join between out-of-order partition key columns does not qualify for -- partitionwise join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFTJOIN prt2_m t2 ON t1.a = t2.b;
-- equi-join between non-key columns does not qualify for partitionwise join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_m t1 LEFTJOIN prt2_m t2 ON t1.c = t2.c;
-- partitionwise join can not be applied for a join between list and range -- partitioned tables EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 LEFTJOIN prt2_n t2 ON (t1.c = t2.c);
-- partitionwise join can not be applied between tables with different -- partition lists EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 JOIN prt2_n t2 ON (t1.c = t2.c) JOIN plt1 t3 ON (t1.c = t3.c);
-- partitionwise join can not be applied for a join between key column and -- non-key column EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_n t1 FULL JOIN prt1 t2 ON (t1.c = t2.c);
-- -- Test some other plan types in a partitionwise join (unfortunately, -- we need larger tables to get the planner to choose these plan types) -- create temp table prtx1 (a integer, b integer, c integer)
partition by range (a); create temp table prtx1_1 partition of prtx1 forvaluesfrom (1) to (11); create temp table prtx1_2 partition of prtx1 forvaluesfrom (11) to (21); create temp table prtx1_3 partition of prtx1 forvaluesfrom (21) to (31); create temp table prtx2 (a integer, b integer, c integer)
partition by range (a); create temp table prtx2_1 partition of prtx2 forvaluesfrom (1) to (11); create temp table prtx2_2 partition of prtx2 forvaluesfrom (11) to (21); create temp table prtx2_3 partition of prtx2 forvaluesfrom (21) to (31); insertinto prtx1 select1 + i%30, i, i from generate_series(1,1000) i; insertinto prtx2 select1 + i%30, i, i from generate_series(1,500) i, generate_series(1,10) j; createindexon prtx2 (b); createindexon prtx2 (c); analyze prtx1; analyze prtx2;
explain (costs off) select * from prtx1 wherenotexists (select1from prtx2 where prtx2.a=prtx1.a and prtx2.b=prtx1.b and prtx2.c=123) and a<20and c=120;
select * from prtx1 wherenotexists (select1from prtx2 where prtx2.a=prtx1.a and prtx2.b=prtx1.b and prtx2.c=123) and a<20and c=120;
explain (costs off) select * from prtx1 wherenotexists (select1from prtx2 where prtx2.a=prtx1.a and (prtx2.b=prtx1.b+1or prtx2.c=99)) and a<20and c=91;
select * from prtx1 wherenotexists (select1from prtx2 where prtx2.a=prtx1.a and (prtx2.b=prtx1.b+1or prtx2.c=99)) and a<20and c=91;
-- -- Test advanced partition-matching algorithm for partitioned join --
-- Tests for range-partitioned tables CREATETABLE prt1_adv (a int, b int, c varchar) PARTITION BY RANGE (a); CREATETABLE prt1_adv_p1 PARTITION OF prt1_adv FORVALUESFROM (100) TO (200); CREATETABLE prt1_adv_p2 PARTITION OF prt1_adv FORVALUESFROM (200) TO (300); CREATETABLE prt1_adv_p3 PARTITION OF prt1_adv FORVALUESFROM (300) TO (400); CREATEINDEX prt1_adv_a_idx ON prt1_adv (a); INSERTINTO prt1_adv SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(100, 399) i; ANALYZE prt1_adv;
CREATETABLE prt2_adv (a int, b int, c varchar) PARTITION BY RANGE (b); CREATETABLE prt2_adv_p1 PARTITION OF prt2_adv FORVALUESFROM (100) TO (150); CREATETABLE prt2_adv_p2 PARTITION OF prt2_adv FORVALUESFROM (200) TO (300); CREATETABLE prt2_adv_p3 PARTITION OF prt2_adv FORVALUESFROM (350) TO (500); CREATEINDEX prt2_adv_b_idx ON prt2_adv (b); INSERTINTO prt2_adv_p1 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(100, 149) i; INSERTINTO prt2_adv_p2 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(200, 299) i; INSERTINTO prt2_adv_p3 SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(350, 499) i; ANALYZE prt2_adv;
-- inner join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- semi join EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1_adv t1 WHEREEXISTS (SELECT1FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0ORDERBY t1.a; SELECT t1.* FROM prt1_adv t1 WHEREEXISTS (SELECT1FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0ORDERBY t1.a;
-- left join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFTJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFTJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- anti join EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1_adv t1 WHERENOTEXISTS (SELECT1FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0ORDERBY t1.a; SELECT t1.* FROM prt1_adv t1 WHERENOTEXISTS (SELECT1FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0ORDERBY t1.a;
-- full join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDERBY t1.a, t2.b;
-- Test cases where one side has an extra partition CREATETABLE prt2_adv_extra PARTITION OF prt2_adv FORVALUESFROM (500) TO (MAXVALUE); INSERTINTO prt2_adv SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(500, 599) i; ANALYZE prt2_adv;
-- inner join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- semi join EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1_adv t1 WHEREEXISTS (SELECT1FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0ORDERBY t1.a; SELECT t1.* FROM prt1_adv t1 WHEREEXISTS (SELECT1FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0ORDERBY t1.a;
-- left join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFTJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFTJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- left join; currently we can't do partitioned join if there are no matched -- partitions on the nullable side EXPLAIN (COSTS OFF) SELECT t1.b, t1.c, t2.a, t2.c FROM prt2_adv t1 LEFTJOIN prt1_adv t2 ON (t1.b = t2.a) WHERE t1.a = 0ORDERBY t1.b, t2.a;
-- anti join EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1_adv t1 WHERENOTEXISTS (SELECT1FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0ORDERBY t1.a; SELECT t1.* FROM prt1_adv t1 WHERENOTEXISTS (SELECT1FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0ORDERBY t1.a;
-- anti join; currently we can't do partitioned join if there are no matched -- partitions on the nullable side EXPLAIN (COSTS OFF) SELECT t1.* FROM prt2_adv t1 WHERENOTEXISTS (SELECT1FROM prt1_adv t2 WHERE t1.b = t2.a) AND t1.a = 0ORDERBY t1.b;
-- full join; currently we can't do partitioned join if there are no matched -- partitions on the nullable side EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDERBY t1.a, t2.b;
-- 3-way join where not every pair of relations can do partitioned join EXPLAIN (COSTS OFF) SELECT t1.b, t1.c, t2.a, t2.c, t3.a, t3.c FROM prt2_adv t1 LEFTJOIN prt1_adv t2 ON (t1.b = t2.a) INNERJOIN prt1_adv t3 ON (t1.b = t3.a) WHERE t1.a = 0ORDERBY t1.b, t2.a, t3.a; SELECT t1.b, t1.c, t2.a, t2.c, t3.a, t3.c FROM prt2_adv t1 LEFTJOIN prt1_adv t2 ON (t1.b = t2.a) INNERJOIN prt1_adv t3 ON (t1.b = t3.a) WHERE t1.a = 0ORDERBY t1.b, t2.a, t3.a;
DROPTABLE prt2_adv_extra;
-- Test cases where a partition on one side matches multiple partitions on -- the other side; we currently can't do partitioned join in such cases ALTERTABLE prt2_adv DETACH PARTITION prt2_adv_p3; -- Split prt2_adv_p3 into two partitions so that prt1_adv_p3 matches both CREATETABLE prt2_adv_p3_1 PARTITION OF prt2_adv FORVALUESFROM (350) TO (375); CREATETABLE prt2_adv_p3_2 PARTITION OF prt2_adv FORVALUESFROM (375) TO (500); INSERTINTO prt2_adv SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(350, 499) i; ANALYZE prt2_adv;
-- inner join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- semi join EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1_adv t1 WHEREEXISTS (SELECT1FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0ORDERBY t1.a;
-- left join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 LEFTJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- anti join EXPLAIN (COSTS OFF) SELECT t1.* FROM prt1_adv t1 WHERENOTEXISTS (SELECT1FROM prt2_adv t2 WHERE t1.a = t2.b) AND t1.b = 0ORDERBY t1.a;
-- full join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM (SELECT175 phv, * FROM prt1_adv WHERE prt1_adv.b = 0) t1 FULL JOIN (SELECT425 phv, * FROM prt2_adv WHERE prt2_adv.a = 0) t2 ON (t1.a = t2.b) WHERE t1.phv = t1.a OR t2.phv = t2.b ORDERBY t1.a, t2.b;
-- Test default partitions ALTERTABLE prt1_adv DETACH PARTITION prt1_adv_p1; -- Change prt1_adv_p1 to the default partition ALTERTABLE prt1_adv ATTACH PARTITION prt1_adv_p1 DEFAULT; ALTERTABLE prt1_adv DETACH PARTITION prt1_adv_p3; ANALYZE prt1_adv;
-- We can do partitioned join even if only one of relations has the default -- partition EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b;
-- Partitioned join can't be applied because the default partition of prt1_adv -- matches prt2_adv_p1 and prt2_adv_p3 EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b;
ALTERTABLE prt2_adv DETACH PARTITION prt2_adv_p3; -- Change prt2_adv_p3 to the default partition ALTERTABLE prt2_adv ATTACH PARTITION prt2_adv_p3 DEFAULT; ANALYZE prt2_adv;
-- Partitioned join can't be applied because the default partition of prt1_adv -- matches prt2_adv_p1 and prt2_adv_p3 EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.b = 0ORDERBY t1.a, t2.b;
DROPTABLE prt1_adv_p3; ANALYZE prt1_adv;
DROPTABLE prt2_adv_p3; ANALYZE prt2_adv;
CREATETABLE prt3_adv (a int, b int, c varchar) PARTITION BY RANGE (a); CREATETABLE prt3_adv_p1 PARTITION OF prt3_adv FORVALUESFROM (200) TO (300); CREATETABLE prt3_adv_p2 PARTITION OF prt3_adv FORVALUESFROM (300) TO (400); CREATEINDEX prt3_adv_a_idx ON prt3_adv (a); INSERTINTO prt3_adv SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(200, 399) i; ANALYZE prt3_adv;
-- 3-way join to test the default partition of a join relation EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c, t3.a, t3.c FROM prt1_adv t1 LEFTJOIN prt2_adv t2 ON (t1.a = t2.b) LEFTJOIN prt3_adv t3 ON (t1.a = t3.a) WHERE t1.b = 0ORDERBY t1.a, t2.b, t3.a; SELECT t1.a, t1.c, t2.b, t2.c, t3.a, t3.c FROM prt1_adv t1 LEFTJOIN prt2_adv t2 ON (t1.a = t2.b) LEFTJOIN prt3_adv t3 ON (t1.a = t3.a) WHERE t1.b = 0ORDERBY t1.a, t2.b, t3.a;
-- Test interaction of partitioned join with partition pruning CREATETABLE prt1_adv (a int, b int, c varchar) PARTITION BY RANGE (a); CREATETABLE prt1_adv_p1 PARTITION OF prt1_adv FORVALUESFROM (100) TO (200); CREATETABLE prt1_adv_p2 PARTITION OF prt1_adv FORVALUESFROM (200) TO (300); CREATETABLE prt1_adv_p3 PARTITION OF prt1_adv FORVALUESFROM (300) TO (400); CREATEINDEX prt1_adv_a_idx ON prt1_adv (a); INSERTINTO prt1_adv SELECT i, i % 25, to_char(i, 'FM0000') FROM generate_series(100, 399) i; ANALYZE prt1_adv;
CREATETABLE prt2_adv (a int, b int, c varchar) PARTITION BY RANGE (b); CREATETABLE prt2_adv_p1 PARTITION OF prt2_adv FORVALUESFROM (100) TO (200); CREATETABLE prt2_adv_p2 PARTITION OF prt2_adv FORVALUESFROM (200) TO (400); CREATEINDEX prt2_adv_b_idx ON prt2_adv (b); INSERTINTO prt2_adv SELECT i % 25, i, to_char(i, 'FM0000') FROM generate_series(100, 399) i; ANALYZE prt2_adv;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a < 300AND t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a < 300AND t1.b = 0ORDERBY t1.a, t2.b;
DROPTABLE prt1_adv_p3; CREATETABLE prt1_adv_default PARTITION OF prt1_adv DEFAULT; ANALYZE prt1_adv;
CREATETABLE prt2_adv_default PARTITION OF prt2_adv DEFAULT; ANALYZE prt2_adv;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a >= 100AND t1.a < 300AND t1.b = 0ORDERBY t1.a, t2.b; SELECT t1.a, t1.c, t2.b, t2.c FROM prt1_adv t1 INNERJOIN prt2_adv t2 ON (t1.a = t2.b) WHERE t1.a >= 100AND t1.a < 300AND t1.b = 0ORDERBY t1.a, t2.b;
DROPTABLE prt1_adv; DROPTABLE prt2_adv;
-- Tests for list-partitioned tables CREATETABLE plt1_adv (a int, b int, c text) PARTITION BY LIST (c); CREATETABLE plt1_adv_p1 PARTITION OF plt1_adv FORVALUESIN ('0001', '0003'); CREATETABLE plt1_adv_p2 PARTITION OF plt1_adv FORVALUESIN ('0004', '0006'); CREATETABLE plt1_adv_p3 PARTITION OF plt1_adv FORVALUESIN ('0008', '0009'); INSERTINTO plt1_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10IN (1, 3, 4, 6, 8, 9); ANALYZE plt1_adv;
CREATETABLE plt2_adv (a int, b int, c text) PARTITION BY LIST (c); CREATETABLE plt2_adv_p1 PARTITION OF plt2_adv FORVALUESIN ('0002', '0003'); CREATETABLE plt2_adv_p2 PARTITION OF plt2_adv FORVALUESIN ('0004', '0006'); CREATETABLE plt2_adv_p3 PARTITION OF plt2_adv FORVALUESIN ('0007', '0009'); INSERTINTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10IN (2, 3, 4, 6, 7, 9); ANALYZE plt2_adv;
-- inner join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- semi join EXPLAIN (COSTS OFF) SELECT t1.* FROM plt1_adv t1 WHEREEXISTS (SELECT1FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a; SELECT t1.* FROM plt1_adv t1 WHEREEXISTS (SELECT1FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a;
-- left join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- anti join EXPLAIN (COSTS OFF) SELECT t1.* FROM plt1_adv t1 WHERENOTEXISTS (SELECT1FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a; SELECT t1.* FROM plt1_adv t1 WHERENOTEXISTS (SELECT1FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a;
-- full join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10AND coalesce(t2.b, 0) < 10ORDERBY t1.a, t2.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10AND coalesce(t2.b, 0) < 10ORDERBY t1.a, t2.a;
-- Test cases where one side has an extra partition CREATETABLE plt2_adv_extra PARTITION OF plt2_adv FORVALUESIN ('0000'); INSERTINTO plt2_adv_extra VALUES (0, 0, '0000'); ANALYZE plt2_adv;
-- inner join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- semi join EXPLAIN (COSTS OFF) SELECT t1.* FROM plt1_adv t1 WHEREEXISTS (SELECT1FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a; SELECT t1.* FROM plt1_adv t1 WHEREEXISTS (SELECT1FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a;
-- left join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- left join; currently we can't do partitioned join if there are no matched -- partitions on the nullable side EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt2_adv t1 LEFTJOIN plt1_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- anti join EXPLAIN (COSTS OFF) SELECT t1.* FROM plt1_adv t1 WHERENOTEXISTS (SELECT1FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a; SELECT t1.* FROM plt1_adv t1 WHERENOTEXISTS (SELECT1FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a;
-- anti join; currently we can't do partitioned join if there are no matched -- partitions on the nullable side EXPLAIN (COSTS OFF) SELECT t1.* FROM plt2_adv t1 WHERENOTEXISTS (SELECT1FROM plt1_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a;
-- full join; currently we can't do partitioned join if there are no matched -- partitions on the nullable side EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10AND coalesce(t2.b, 0) < 10ORDERBY t1.a, t2.a;
DROPTABLE plt2_adv_extra;
-- Test cases where a partition on one side matches multiple partitions on -- the other side; we currently can't do partitioned join in such cases ALTERTABLE plt2_adv DETACH PARTITION plt2_adv_p2; -- Split plt2_adv_p2 into two partitions so that plt1_adv_p2 matches both CREATETABLE plt2_adv_p2_1 PARTITION OF plt2_adv FORVALUESIN ('0004'); CREATETABLE plt2_adv_p2_2 PARTITION OF plt2_adv FORVALUESIN ('0006'); INSERTINTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10IN (4, 6); ANALYZE plt2_adv;
-- inner join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- semi join EXPLAIN (COSTS OFF) SELECT t1.* FROM plt1_adv t1 WHEREEXISTS (SELECT1FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a;
-- left join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- anti join EXPLAIN (COSTS OFF) SELECT t1.* FROM plt1_adv t1 WHERENOTEXISTS (SELECT1FROM plt2_adv t2 WHERE t1.a = t2.a AND t1.c = t2.c) AND t1.b < 10ORDERBY t1.a;
-- full join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10AND coalesce(t2.b, 0) < 10ORDERBY t1.a, t2.a;
-- inner join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- left join; currently we can't do partitioned join if there are no matched -- partitions on the nullable side EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- full join; currently we can't do partitioned join if there are no matched -- partitions on the nullable side EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10AND coalesce(t2.b, 0) < 10ORDERBY t1.a, t2.a;
-- Add to plt2_adv the extra NULL partition containing only NULL values as the -- key values CREATETABLE plt2_adv_extra PARTITION OF plt2_adv FORVALUESIN (NULL); INSERTINTO plt2_adv VALUES (-1, -1, NULL); ANALYZE plt2_adv;
-- inner join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- left join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- full join EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10AND coalesce(t2.b, 0) < 10ORDERBY t1.a, t2.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 FULL JOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE coalesce(t1.b, 0) < 10AND coalesce(t2.b, 0) < 10ORDERBY t1.a, t2.a;
-- 3-way join to test the NULL partition of a join relation EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFTJOIN plt1_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFTJOIN plt1_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10ORDERBY t1.a;
-- Test default partitions ALTERTABLE plt1_adv DETACH PARTITION plt1_adv_p1; -- Change plt1_adv_p1 to the default partition ALTERTABLE plt1_adv ATTACH PARTITION plt1_adv_p1 DEFAULT; DROPTABLE plt1_adv_p3; ANALYZE plt1_adv;
DROPTABLE plt2_adv_p3; ANALYZE plt2_adv;
-- We can do partitioned join even if only one of relations has the default -- partition EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
ALTERTABLE plt2_adv DETACH PARTITION plt2_adv_p2; -- Change plt2_adv_p2 to contain '0005' in addition to '0004' and '0006' as -- the key values CREATETABLE plt2_adv_p2_ext PARTITION OF plt2_adv FORVALUESIN ('0004', '0005', '0006'); INSERTINTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10IN (4, 5, 6); ANALYZE plt2_adv;
-- Partitioned join can't be applied because the default partition of plt1_adv -- matches plt2_adv_p1 and plt2_adv_p2_ext EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
ALTERTABLE plt2_adv DETACH PARTITION plt2_adv_p2_ext; -- Change plt2_adv_p2_ext to the default partition ALTERTABLE plt2_adv ATTACH PARTITION plt2_adv_p2_ext DEFAULT; ANALYZE plt2_adv;
-- Partitioned join can't be applied because the default partition of plt1_adv -- matches plt2_adv_p1 and plt2_adv_p2_ext EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
CREATETABLE plt3_adv (a int, b int, c text) PARTITION BY LIST (c); CREATETABLE plt3_adv_p1 PARTITION OF plt3_adv FORVALUESIN ('0004', '0006'); CREATETABLE plt3_adv_p2 PARTITION OF plt3_adv FORVALUESIN ('0007', '0009'); INSERTINTO plt3_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10IN (4, 6, 7, 9); ANALYZE plt3_adv;
-- 3-way join to test the default partition of a join relation EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFTJOIN plt3_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) LEFTJOIN plt3_adv t3 ON (t1.a = t3.a AND t1.c = t3.c) WHERE t1.b < 10ORDERBY t1.a;
-- Test cases where one side has the default partition while the other side -- has the NULL partition DROPTABLE plt2_adv_p1; -- Add the NULL partition to plt2_adv CREATETABLE plt2_adv_p1_null PARTITION OF plt2_adv FORVALUESIN (NULL, '0001', '0003'); INSERTINTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10IN (1, 3); INSERTINTO plt2_adv VALUES (-1, -1, NULL); ANALYZE plt2_adv;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
DROPTABLE plt2_adv_p1_null; -- Add the NULL partition that contains only NULL values as the key values CREATETABLE plt2_adv_p1_null PARTITION OF plt2_adv FORVALUESIN (NULL); INSERTINTO plt2_adv VALUES (-1, -1, NULL); ANALYZE plt2_adv;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.b < 10ORDERBY t1.a;
-- Test interaction of partitioned join with partition pruning CREATETABLE plt1_adv (a int, b int, c text) PARTITION BY LIST (c); CREATETABLE plt1_adv_p1 PARTITION OF plt1_adv FORVALUESIN ('0001'); CREATETABLE plt1_adv_p2 PARTITION OF plt1_adv FORVALUESIN ('0002'); CREATETABLE plt1_adv_p3 PARTITION OF plt1_adv FORVALUESIN ('0003'); CREATETABLE plt1_adv_p4 PARTITION OF plt1_adv FORVALUESIN (NULL, '0004', '0005'); INSERTINTO plt1_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10IN (1, 2, 3, 4, 5); INSERTINTO plt1_adv VALUES (-1, -1, NULL); ANALYZE plt1_adv;
CREATETABLE plt2_adv (a int, b int, c text) PARTITION BY LIST (c); CREATETABLE plt2_adv_p1 PARTITION OF plt2_adv FORVALUESIN ('0001', '0002'); CREATETABLE plt2_adv_p2 PARTITION OF plt2_adv FORVALUESIN (NULL); CREATETABLE plt2_adv_p3 PARTITION OF plt2_adv FORVALUESIN ('0003'); CREATETABLE plt2_adv_p4 PARTITION OF plt2_adv FORVALUESIN ('0004', '0005'); INSERTINTO plt2_adv SELECT i, i, to_char(i % 10, 'FM0000') FROM generate_series(1, 299) i WHERE i % 10IN (1, 2, 3, 4, 5); INSERTINTO plt2_adv VALUES (-1, -1, NULL); ANALYZE plt2_adv;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10ORDERBY t1.a;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c ISNULLAND t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c ISNULLAND t1.b < 10ORDERBY t1.a;
CREATETABLE plt1_adv_default PARTITION OF plt1_adv DEFAULT; ANALYZE plt1_adv;
CREATETABLE plt2_adv_default PARTITION OF plt2_adv DEFAULT; ANALYZE plt2_adv;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 INNERJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c IN ('0003', '0004', '0005') AND t1.b < 10ORDERBY t1.a;
EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c ISNULLAND t1.b < 10ORDERBY t1.a; SELECT t1.a, t1.c, t2.a, t2.c FROM plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE t1.c ISNULLAND t1.b < 10ORDERBY t1.a;
DROPTABLE plt1_adv; DROPTABLE plt2_adv;
-- Test the process_outer_partition() code path CREATETABLE plt1_adv (a int, b int, c text) PARTITION BY LIST (c); CREATETABLE plt1_adv_p1 PARTITION OF plt1_adv FORVALUESIN ('0000', '0001', '0002'); CREATETABLE plt1_adv_p2 PARTITION OF plt1_adv FORVALUESIN ('0003', '0004'); INSERTINTO plt1_adv SELECT i, i, to_char(i % 5, 'FM0000') FROM generate_series(0, 24) i; ANALYZE plt1_adv;
CREATETABLE plt2_adv (a int, b int, c text) PARTITION BY LIST (c); CREATETABLE plt2_adv_p1 PARTITION OF plt2_adv FORVALUESIN ('0002'); CREATETABLE plt2_adv_p2 PARTITION OF plt2_adv FORVALUESIN ('0003', '0004'); INSERTINTO plt2_adv SELECT i, i, to_char(i % 5, 'FM0000') FROM generate_series(0, 24) i WHEREi % 5IN (2, 3, 4); ANALYZE plt2_adv;
CREATETABLE plt3_adv (a int, b int, c text) PARTITION BY LIST (c); CREATETABLE plt3_adv_p1 PARTITION OF plt3_adv FORVALUESIN ('0001'); CREATETABLE plt3_adv_p2 PARTITION OF plt3_adv FORVALUESIN ('0003', '0004'); INSERTINTO plt3_adv SELECT i, i, to_char(i % 5, 'FM0000') FROM generate_series(0, 24) i WHEREi % 5IN (1, 3, 4); ANALYZE plt3_adv;
-- This tests that when merging partitions from plt1_adv and plt2_adv in -- merge_list_bounds(), process_outer_partition() returns an already-assigned -- merged partition when re-called with plt1_adv_p1 for the second list value -- '0001' of that partition EXPLAIN (COSTS OFF) SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM (plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.c = t2.c)) FULL JOIN plt3_adv t3 ON (t1.c = t3.c) WHERE coalesce(t1.a, 0) % 5 != 3AND coalesce(t1.a, 0) % 5 != 4ORDERBY t1.c, t1.a, t2.a, t3.a; SELECT t1.a, t1.c, t2.a, t2.c, t3.a, t3.c FROM (plt1_adv t1 LEFTJOIN plt2_adv t2 ON (t1.c = t2.c)) FULL JOIN plt3_adv t3 ON (t1.c = t3.c) WHERE coalesce(t1.a, 0) % 5 != 3AND coalesce(t1.a, 0) % 5 != 4ORDERBY t1.c, t1.a, t2.a, t3.a;
-- Tests for multi-level partitioned tables CREATETABLE alpha (a doubleprecision, b int, c text) PARTITION BY RANGE (a); CREATETABLE alpha_neg PARTITION OF alpha FORVALUESFROM ('-Infinity') TO (0) PARTITION BY RANGE (b); CREATETABLE alpha_pos PARTITION OF alpha FORVALUESFROM (0) TO (10.0) PARTITION BY LIST (c); CREATETABLE alpha_neg_p1 PARTITION OF alpha_neg FORVALUESFROM (100) TO (200); CREATETABLE alpha_neg_p2 PARTITION OF alpha_neg FORVALUESFROM (200) TO (300); CREATETABLE alpha_neg_p3 PARTITION OF alpha_neg FORVALUESFROM (300) TO (400); CREATETABLE alpha_pos_p1 PARTITION OF alpha_pos FORVALUESIN ('0001', '0003'); CREATETABLE alpha_pos_p2 PARTITION OF alpha_pos FORVALUESIN ('0004', '0006'); CREATETABLE alpha_pos_p3 PARTITION OF alpha_pos FORVALUESIN ('0008', '0009'); INSERTINTO alpha_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 399) i WHERE i % 10IN (1, 3, 4, 6, 8, 9); INSERTINTO alpha_pos SELECT1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 399) i WHERE i % 10IN (1, 3, 4, 6, 8, 9); ANALYZE alpha;
CREATETABLE beta (a doubleprecision, b int, c text) PARTITION BY RANGE (a); CREATETABLE beta_neg PARTITION OF beta FORVALUESFROM (-10.0) TO (0) PARTITION BY RANGE (b); CREATETABLE beta_pos PARTITION OF beta FORVALUESFROM (0) TO ('Infinity') PARTITION BY LIST (c); CREATETABLE beta_neg_p1 PARTITION OF beta_neg FORVALUESFROM (100) TO (150); CREATETABLE beta_neg_p2 PARTITION OF beta_neg FORVALUESFROM (200) TO (300); CREATETABLE beta_neg_p3 PARTITION OF beta_neg FORVALUESFROM (350) TO (500); CREATETABLE beta_pos_p1 PARTITION OF beta_pos FORVALUESIN ('0002', '0003'); CREATETABLE beta_pos_p2 PARTITION OF beta_pos FORVALUESIN ('0004', '0006'); CREATETABLE beta_pos_p3 PARTITION OF beta_pos FORVALUESIN ('0007', '0009'); INSERTINTO beta_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 149) i WHERE i % 10IN (2, 3, 4, 6, 7, 9); INSERTINTO beta_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(200, 299) i WHERE i % 10IN (2, 3, 4, 6, 7, 9); INSERTINTO beta_neg SELECT -1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(350, 499) i WHERE i % 10IN (2, 3, 4, 6, 7, 9); INSERTINTO beta_pos SELECT1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(100, 149) i WHERE i % 10IN (2, 3, 4, 6, 7, 9); INSERTINTO beta_pos SELECT1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(200, 299) i WHERE i % 10IN (2, 3, 4, 6, 7, 9); INSERTINTO beta_pos SELECT1.0, i, to_char(i % 10, 'FM0000') FROM generate_series(350, 499) i WHERE i % 10IN (2, 3, 4, 6, 7, 9); ANALYZE beta;
EXPLAIN (COSTS OFF) SELECT t1.*, t2.* FROM alpha t1 INNERJOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b) WHERE t1.b >= 125AND t1.b < 225ORDERBY t1.a, t1.b; SELECT t1.*, t2.* FROM alpha t1 INNERJOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b) WHERE t1.b >= 125AND t1.b < 225ORDERBY t1.a, t1.b;
EXPLAIN (COSTS OFF) SELECT t1.*, t2.* FROM alpha t1 INNERJOIN beta t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE ((t1.b >= 100AND t1.b < 110) OR (t1.b >= 200AND t1.b < 210)) AND ((t2.b >= 100AND t2.b < 110) OR (t2.b >= 200AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDERBY t1.a, t1.b, t2.b; SELECT t1.*, t2.* FROM alpha t1 INNERJOIN beta t2 ON (t1.a = t2.a AND t1.c = t2.c) WHERE ((t1.b >= 100AND t1.b < 110) OR (t1.b >= 200AND t1.b < 210)) AND ((t2.b >= 100AND t2.b < 110) OR (t2.b >= 200AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDERBY t1.a, t1.b, t2.b;
EXPLAIN (COSTS OFF) SELECT t1.*, t2.* FROM alpha t1 INNERJOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) WHERE ((t1.b >= 100AND t1.b < 110) OR (t1.b >= 200AND t1.b < 210)) AND ((t2.b >= 100AND t2.b < 110) OR (t2.b >= 200AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDERBY t1.a, t1.b; SELECT t1.*, t2.* FROM alpha t1 INNERJOIN beta t2 ON (t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) WHERE ((t1.b >= 100AND t1.b < 110) OR (t1.b >= 200AND t1.b < 210)) AND ((t2.b >= 100AND t2.b < 110) OR (t2.b >= 200AND t2.b < 210)) AND t1.c IN ('0004', '0009') ORDERBY t1.a, t1.b;
-- partitionwise join with fractional paths CREATETABLE fract_t (id BIGINT, PRIMARYKEY (id)) PARTITION BY RANGE (id); CREATETABLE fract_t0 PARTITION OF fract_t FORVALUESFROM ('0') TO ('1000'); CREATETABLE fract_t1 PARTITION OF fract_t FORVALUESFROM ('1000') TO ('2000');
-- verify plan; nested index only scans SET max_parallel_workers_per_gather = 0; SET enable_partitionwise_join = on;
EXPLAIN (COSTS OFF) SELECT x.id, y.id FROM fract_t x LEFTJOIN fract_t y USING (id) ORDERBY x.id ASCLIMIT10;
EXPLAIN (COSTS OFF) SELECT x.id, y.id FROM fract_t x LEFTJOIN fract_t y USING (id) ORDERBY x.id DESCLIMIT10; EXPLAIN (COSTS OFF) -- Should use NestLoop with parameterised inner scan SELECT x.id, y.id FROM fract_t x LEFTJOIN fract_t y USING (id) ORDERBY x.id DESCLIMIT2;
-- -- Test Append's fractional paths --
CREATEINDEX pht1_c_idx ON pht1(c); -- SeqScan might be the best choice if we need one single tuple EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT1; -- Increase number of tuples requested and an IndexScan will be chosen EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT100; -- If almost all the data should be fetched - prefer SeqScan EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT1000;
SET max_parallel_workers_per_gather = 1; SET debug_parallel_query = on; -- Partial paths should also be smart enough to employ limits EXPLAIN (COSTS OFF) SELECT * FROM pht1 p1 JOIN pht1 p2 USING (c) LIMIT100;
RESET debug_parallel_query;
-- Remove indexes from the partitioned table and its partitions DROPINDEX pht1_c_idx CASCADE;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.