mirror of
https://github.com/postgres/postgres.git
synced 2026-03-23 02:43:22 -04:00
146 lines
5.4 KiB
MySQL
146 lines
5.4 KiB
MySQL
|
|
LOAD 'pg_plan_advice';
|
||
|
|
SET max_parallel_workers_per_gather = 0;
|
||
|
|
|
||
|
|
CREATE TABLE jo_dim1 (id integer primary key, dim1 text, val1 int)
|
||
|
|
WITH (autovacuum_enabled = false);
|
||
|
|
INSERT INTO jo_dim1 (id, dim1, val1)
|
||
|
|
SELECT g, 'some filler text ' || g, (g % 3) + 1
|
||
|
|
FROM generate_series(1,100) g;
|
||
|
|
VACUUM ANALYZE jo_dim1;
|
||
|
|
CREATE TABLE jo_dim2 (id integer primary key, dim2 text, val2 int)
|
||
|
|
WITH (autovacuum_enabled = false);
|
||
|
|
INSERT INTO jo_dim2 (id, dim2, val2)
|
||
|
|
SELECT g, 'some filler text ' || g, (g % 53) + 1
|
||
|
|
FROM generate_series(1,1000) g;
|
||
|
|
VACUUM ANALYZE jo_dim2;
|
||
|
|
|
||
|
|
CREATE TABLE jo_fact (
|
||
|
|
id int primary key,
|
||
|
|
dim1_id integer not null references jo_dim1 (id),
|
||
|
|
dim2_id integer not null references jo_dim2 (id)
|
||
|
|
) WITH (autovacuum_enabled = false);
|
||
|
|
INSERT INTO jo_fact
|
||
|
|
SELECT g, (g%100)+1, (g%100)+1 FROM generate_series(1,100000) g;
|
||
|
|
VACUUM ANALYZE jo_fact;
|
||
|
|
|
||
|
|
-- We expect to join to d2 first and then d1, since the condition on d2
|
||
|
|
-- is more selective.
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_fact f
|
||
|
|
LEFT JOIN jo_dim1 d1 ON f.dim1_id = d1.id
|
||
|
|
LEFT JOIN jo_dim2 d2 ON f.dim2_id = d2.id
|
||
|
|
WHERE val1 = 1 AND val2 = 1;
|
||
|
|
|
||
|
|
-- Force a few different join orders. Some of these are very inefficient,
|
||
|
|
-- but the planner considers them all viable.
|
||
|
|
BEGIN;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(f d1 d2)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_fact f
|
||
|
|
LEFT JOIN jo_dim1 d1 ON f.dim1_id = d1.id
|
||
|
|
LEFT JOIN jo_dim2 d2 ON f.dim2_id = d2.id
|
||
|
|
WHERE val1 = 1 AND val2 = 1;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(f d2 d1)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_fact f
|
||
|
|
LEFT JOIN jo_dim1 d1 ON f.dim1_id = d1.id
|
||
|
|
LEFT JOIN jo_dim2 d2 ON f.dim2_id = d2.id
|
||
|
|
WHERE val1 = 1 AND val2 = 1;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(d1 f d2)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_fact f
|
||
|
|
LEFT JOIN jo_dim1 d1 ON f.dim1_id = d1.id
|
||
|
|
LEFT JOIN jo_dim2 d2 ON f.dim2_id = d2.id
|
||
|
|
WHERE val1 = 1 AND val2 = 1;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(f (d1 d2))';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_fact f
|
||
|
|
LEFT JOIN jo_dim1 d1 ON f.dim1_id = d1.id
|
||
|
|
LEFT JOIN jo_dim2 d2 ON f.dim2_id = d2.id
|
||
|
|
WHERE val1 = 1 AND val2 = 1;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(f {d1 d2})';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_fact f
|
||
|
|
LEFT JOIN jo_dim1 d1 ON f.dim1_id = d1.id
|
||
|
|
LEFT JOIN jo_dim2 d2 ON f.dim2_id = d2.id
|
||
|
|
WHERE val1 = 1 AND val2 = 1;
|
||
|
|
COMMIT;
|
||
|
|
|
||
|
|
-- Force a join order by mentioning just a prefix of the join list.
|
||
|
|
BEGIN;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(d2)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_fact f
|
||
|
|
LEFT JOIN jo_dim1 d1 ON f.dim1_id = d1.id
|
||
|
|
LEFT JOIN jo_dim2 d2 ON f.dim2_id = d2.id
|
||
|
|
WHERE val1 = 1 AND val2 = 1;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(d2 d1)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_fact f
|
||
|
|
LEFT JOIN jo_dim1 d1 ON f.dim1_id = d1.id
|
||
|
|
LEFT JOIN jo_dim2 d2 ON f.dim2_id = d2.id
|
||
|
|
WHERE val1 = 1 AND val2 = 1;
|
||
|
|
COMMIT;
|
||
|
|
|
||
|
|
-- jo_fact is not partitioned, but let's try pretending that it is and
|
||
|
|
-- verifying that the advice does not apply.
|
||
|
|
BEGIN;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(f/d1 d1 d2)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_fact f
|
||
|
|
LEFT JOIN jo_dim1 d1 ON f.dim1_id = d1.id
|
||
|
|
LEFT JOIN jo_dim2 d2 ON f.dim2_id = d2.id
|
||
|
|
WHERE val1 = 1 AND val2 = 1;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(f/d1 (d1 d2))';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_fact f
|
||
|
|
LEFT JOIN jo_dim1 d1 ON f.dim1_id = d1.id
|
||
|
|
LEFT JOIN jo_dim2 d2 ON f.dim2_id = d2.id
|
||
|
|
WHERE val1 = 1 AND val2 = 1;
|
||
|
|
COMMIT;
|
||
|
|
|
||
|
|
-- The unusual formulation of this query is intended to prevent the query
|
||
|
|
-- planner from reducing the FULL JOIN to some other join type, so that we
|
||
|
|
-- can test what happens with a join type that cannot be reordered.
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_dim1 d1
|
||
|
|
INNER JOIN (jo_fact f FULL JOIN jo_dim2 d2 ON f.dim2_id + 0 = d2.id + 0)
|
||
|
|
ON d1.id = f.dim1_id OR f.dim1_id IS NULL;
|
||
|
|
|
||
|
|
-- We should not be able to force the planner to join f to d1 first, because
|
||
|
|
-- that is not a valid join order, but we should be able to force the planner
|
||
|
|
-- to make either d2 or f the driving table.
|
||
|
|
BEGIN;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(f d1 d2)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_dim1 d1
|
||
|
|
INNER JOIN (jo_fact f FULL JOIN jo_dim2 d2 ON f.dim2_id + 0 = d2.id + 0)
|
||
|
|
ON d1.id = f.dim1_id OR f.dim1_id IS NULL;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(f d2 d1)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_dim1 d1
|
||
|
|
INNER JOIN (jo_fact f FULL JOIN jo_dim2 d2 ON f.dim2_id + 0 = d2.id + 0)
|
||
|
|
ON d1.id = f.dim1_id OR f.dim1_id IS NULL;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(d2 f d1)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_dim1 d1
|
||
|
|
INNER JOIN (jo_fact f FULL JOIN jo_dim2 d2 ON f.dim2_id + 0 = d2.id + 0)
|
||
|
|
ON d1.id = f.dim1_id OR f.dim1_id IS NULL;
|
||
|
|
COMMIT;
|
||
|
|
|
||
|
|
-- Two incompatible join orders should conflict. In the second case,
|
||
|
|
-- the conflict is implicit: if d1 is on the inner side of a join of any
|
||
|
|
-- type, it cannot also be the driving table.
|
||
|
|
BEGIN;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(f) join_order(d1)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_dim1 d1
|
||
|
|
INNER JOIN (jo_fact f FULL JOIN jo_dim2 d2 ON f.dim2_id + 0 = d2.id + 0)
|
||
|
|
ON d1.id = f.dim1_id OR f.dim1_id IS NULL;
|
||
|
|
SET LOCAL pg_plan_advice.advice = 'join_order(d1) hash_join(d1)';
|
||
|
|
EXPLAIN (COSTS OFF, PLAN_ADVICE)
|
||
|
|
SELECT * FROM jo_dim1 d1
|
||
|
|
INNER JOIN (jo_fact f FULL JOIN jo_dim2 d2 ON f.dim2_id + 0 = d2.id + 0)
|
||
|
|
ON d1.id = f.dim1_id OR f.dim1_id IS NULL;
|
||
|
|
COMMIT;
|