blob: b8639f9fb9c2847b9556616096c730b96b288d08 [file] [log] [blame]
--
-- CBDB PARALLEL
-- Test CBDB style parallel plan.
-- GUCs shoule be set with local, do not disturb other parallel plans.
-- Should not use force_parallel_mode as it will ignore plan and check results only.
-- We want to check plan in this file!
-- If there is need to do that, set it local inside a transaction.
-- Set optimizer off in this file, ORCA parallel is not supported.
--
-- Locus check expression:
-- This is just used to check locus codes in cdbpath_motion_for_parallel_join/cdbpathlocus_parallel_join
-- with corresponding examples quickly for parallel join.
-- Format:
-- 1_2_3 means locus 1 join locus 2 generate locus 3.
-- 1_P_2_3 means locus 1 Join(with shared hash table) locus 2 generate locus 3.
-- All this format represents for parallel join, while P implies it's a parallel_aware join.
--
-- The numbers steal from CdbLocusType enum.
-- 0 CdbLocusType_Null
-- 1 CdbLocusType_Entry
-- 2 CdbLocusType_SingleQE
-- 3 CdbLocusType_General
-- 4 CdbLocusType_SegmentGeneral
-- 5 CdbLocusType_SegmentGeneralWorkers
-- 6 CdbLocusType_OuterQuery
-- 7 CdbLocusType_Replicated
-- 8 CdbLocusType_ReplicatedWorkers
-- 9 CdbLocusType_Hashed
-- 10 CdbLocusType_HashedOJ
-- 11 CdbLocusType_Strewn
-- 12 CdbLocusType_HashedWorkers
--
--
set force_parallel_mode = 0;
set optimizer = off;
create schema test_parallel;
set search_path to test_parallel;
-- set this to default in case regress change it by gpstop.
set gp_appendonly_insert_files = 4;
--
-- Parallel Parallel Join: DEDUP_SEMI and DEDUP_SEMI_REVERSE
--
begin;
create table foo(a int) with(parallel_workers=2) distributed randomly;
create table bar(b int) with(parallel_workers=2) distributed randomly;
insert into foo select i from generate_series(1, 1000)i;
insert into bar select i from generate_series(1, 20000)i;
analyze foo;
analyze bar;
-- non-parallel
set local enable_parallel = off;
explain (costs off)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
QUERY PLAN
---------------------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 3:1 (slice1; segments: 3)
-> Partial Aggregate
-> HashAggregate
Group Key: (RowIdExpr)
-> Redistribute Motion 3:3 (slice2; segments: 3)
Hash Key: (RowIdExpr)
-> Hash Join
Hash Cond: (bar.b = foo.a)
-> Seq Scan on bar
-> Hash
-> Broadcast Motion 3:3 (slice3; segments: 3)
-> Seq Scan on foo
Optimizer: Postgres query optimizer
(14 rows)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
sum
--------
500500
(1 row)
set local enable_parallel = on;
-- Parallel DEDUP_SEMI
set local enable_parallel_semi_join = off;
set local enable_parallel_dedup_semi_reverse_join = off;
explain (costs off)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
QUERY PLAN
-----------------------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 6:1 (slice1; segments: 6)
-> Partial Aggregate
-> HashAggregate
Group Key: (RowIdExpr)
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: (RowIdExpr)
Hash Module: 3
-> Parallel Hash Join
Hash Cond: (foo.a = bar.b)
-> Broadcast Workers Motion 6:6 (slice3; segments: 6)
-> Parallel Seq Scan on foo
-> Parallel Hash
-> Parallel Seq Scan on bar
Optimizer: Postgres query optimizer
(15 rows)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
sum
--------
500500
(1 row)
-- Parallel DEDUP_SEMI_REVERSE
set local enable_parallel_semi_join = off;
set local enable_parallel_dedup_semi_reverse_join = on;
set local enable_parallel_dedup_semi_join = on;
explain (costs off)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
QUERY PLAN
------------------------------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 6:1 (slice1; segments: 6)
-> Partial Aggregate
-> HashAggregate
Group Key: (RowIdExpr)
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: (RowIdExpr)
Hash Module: 3
-> Parallel Hash Join
Hash Cond: (bar.b = foo.a)
-> Parallel Seq Scan on bar
-> Parallel Hash
-> Broadcast Workers Motion 6:6 (slice3; segments: 6)
-> Parallel Seq Scan on foo
Optimizer: Postgres query optimizer
(15 rows)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
sum
--------
500500
(1 row)
-- Parallel oblivious
set local enable_parallel_hash = off;
explain (costs off)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
QUERY PLAN
---------------------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 6:1 (slice1; segments: 6)
-> Partial Aggregate
-> HashAggregate
Group Key: (RowIdExpr)
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: (RowIdExpr)
Hash Module: 3
-> Hash Join
Hash Cond: (bar.b = foo.a)
-> Parallel Seq Scan on bar
-> Hash
-> Broadcast Motion 3:6 (slice3; segments: 3)
-> Seq Scan on foo
Optimizer: Postgres query optimizer
(15 rows)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
sum
--------
500500
(1 row)
set local enable_parallel_dedup_semi_reverse_join = off;
explain (costs off)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
QUERY PLAN
---------------------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 3:1 (slice1; segments: 3)
-> Partial Aggregate
-> HashAggregate
Group Key: (RowIdExpr)
-> Redistribute Motion 3:3 (slice2; segments: 3)
Hash Key: (RowIdExpr)
-> Hash Join
Hash Cond: (bar.b = foo.a)
-> Seq Scan on bar
-> Hash
-> Broadcast Motion 3:3 (slice3; segments: 3)
-> Seq Scan on foo
Optimizer: Postgres query optimizer
(14 rows)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
sum
--------
500500
(1 row)
-- Parallel Nestloop DEDUP_SEMI
set local min_parallel_table_scan_size = 0;
set local enable_parallel_semi_join = off;
set local enable_nestloop = on;
set local enable_hashjoin = off;
set local enable_mergejoin = off;
set local enable_parallel_semi_join = off;
set local enable_parallel_dedup_semi_reverse_join = off;
set local enable_parallel_dedup_semi_join = on;
explain (costs off)
select sum(bar.b) from bar where exists (select 1 from foo where foo.a = bar.b);
QUERY PLAN
------------------------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 6:1 (slice1; segments: 6)
-> Partial Aggregate
-> HashAggregate
Group Key: (RowIdExpr)
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: (RowIdExpr)
Hash Module: 3
-> Nested Loop
Join Filter: (bar.b = foo.a)
-> Redistribute Motion 6:6 (slice3; segments: 6)
Hash Key: bar.b
Hash Module: 3
-> Parallel Seq Scan on bar
-> Materialize
-> Redistribute Motion 3:6 (slice4; segments: 3)
Hash Key: foo.a
Hash Module: 3
-> Seq Scan on foo
Optimizer: Postgres query optimizer
(20 rows)
select sum(bar.b) from bar where exists (select 1 from foo where foo.a = bar.b);
sum
--------
500500
(1 row)
-- Parallel Nestloop DEDUP_SEMI_REVERSE
set local enable_parallel_dedup_semi_reverse_join = on;
set local enable_parallel_dedup_semi_join = off;
explain (costs off)
select sum(bar.b) from bar where exists (select 1 from foo where foo.a = bar.b);
QUERY PLAN
------------------------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 6:1 (slice1; segments: 6)
-> Partial Aggregate
-> HashAggregate
Group Key: (RowIdExpr)
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: (RowIdExpr)
Hash Module: 3
-> Nested Loop
Join Filter: (bar.b = foo.a)
-> Redistribute Motion 6:6 (slice3; segments: 6)
Hash Key: foo.a
Hash Module: 3
-> Parallel Seq Scan on foo
-> Materialize
-> Redistribute Motion 3:6 (slice4; segments: 3)
Hash Key: bar.b
Hash Module: 3
-> Seq Scan on bar
Optimizer: Postgres query optimizer
(20 rows)
select sum(bar.b) from bar where exists (select 1 from foo where foo.a = bar.b);
sum
--------
500500
(1 row)
-- Parallel Mergejoin DEDUP_SEMI
set local enable_parallel_semi_join = off;
set local enable_hashjoin = off;
set local enable_mergejoin = on;
set local enable_nestloop = off;
set local enable_parallel_semi_join = off;
set local enable_parallel_dedup_semi_reverse_join = off;
set local enable_parallel_dedup_semi_join = on;
explain (costs off)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
QUERY PLAN
---------------------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 3:1 (slice1; segments: 3)
-> Partial Aggregate
-> HashAggregate
Group Key: (RowIdExpr)
-> Redistribute Motion 3:3 (slice2; segments: 3)
Hash Key: (RowIdExpr)
-> Merge Join
Merge Cond: (foo.a = bar.b)
-> Sort
Sort Key: foo.a
-> Broadcast Motion 6:3 (slice3; segments: 6)
-> Parallel Seq Scan on foo
-> Sort
Sort Key: bar.b
-> Seq Scan on bar
Optimizer: Postgres query optimizer
(17 rows)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
sum
--------
500500
(1 row)
-- Parallel Mergejoin DEDUP_SEMI_REVERSE
set local enable_parallel_dedup_semi_reverse_join = on;
set local enable_parallel_dedup_semi_join = off;
explain (costs off)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
QUERY PLAN
---------------------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 6:1 (slice1; segments: 6)
-> Partial Aggregate
-> HashAggregate
Group Key: (RowIdExpr)
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: (RowIdExpr)
Hash Module: 3
-> Merge Join
Merge Cond: (bar.b = foo.a)
-> Sort
Sort Key: bar.b
-> Parallel Seq Scan on bar
-> Sort
Sort Key: foo.a
-> Broadcast Motion 3:6 (slice3; segments: 3)
-> Seq Scan on foo
Optimizer: Postgres query optimizer
(18 rows)
select sum(foo.a) from foo where exists (select 1 from bar where foo.a = bar.b);
sum
--------
500500
(1 row)
abort;
-- CBDB(#131): test parallel_workers during create AO/AOCO table take effect
begin;
set local enable_parallel = on;
create table test_131_ao1(x int, y int) using ao_row with(parallel_workers=2);
create table test_131_ao2(x int, y int) using ao_row with(parallel_workers=2);
create table test_131_ao3(x int, y int) using ao_row with(parallel_workers=0);
create table test_131_ao4(x int, y int) using ao_row with(parallel_workers=0);
create table test_131_aoco1(x int, y int) using ao_column with(parallel_workers=2);
create table test_131_aoco2(x int, y int) using ao_column with(parallel_workers=2);
create table test_131_aoco3(x int, y int) using ao_column with(parallel_workers=0);
create table test_131_aoco4(x int, y int) using ao_column with(parallel_workers=0);
select relname, reloptions from pg_catalog.pg_class where relname like 'test_131_ao%';
relname | reloptions
----------------+----------------------
test_131_ao1 | {parallel_workers=2}
test_131_ao2 | {parallel_workers=2}
test_131_ao3 | {parallel_workers=0}
test_131_ao4 | {parallel_workers=0}
test_131_aoco1 | {parallel_workers=2}
test_131_aoco2 | {parallel_workers=2}
test_131_aoco3 | {parallel_workers=0}
test_131_aoco4 | {parallel_workers=0}
(8 rows)
explain(locus, costs off) select count(*) from test_131_ao1, test_131_ao2 where test_131_ao1.x = test_131_ao2.x;
QUERY PLAN
------------------------------------------------------------------
Finalize Aggregate
Locus: Entry
-> Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Hash Join
Locus: HashedWorkers
Parallel Workers: 2
Hash Cond: (test_131_ao1.x = test_131_ao2.x)
-> Parallel Seq Scan on test_131_ao1
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Hash
Locus: Hashed
-> Parallel Seq Scan on test_131_ao2
Locus: HashedWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(20 rows)
explain(locus, costs off) select count(*) from test_131_ao3, test_131_ao4 where test_131_ao3.x = test_131_ao4.x;
QUERY PLAN
------------------------------------------------------------------
Finalize Aggregate
Locus: Entry
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Partial Aggregate
Locus: Hashed
-> Hash Join
Locus: Hashed
Hash Cond: (test_131_ao3.x = test_131_ao4.x)
-> Seq Scan on test_131_ao3
Locus: Hashed
-> Hash
Locus: Hashed
-> Seq Scan on test_131_ao4
Locus: Hashed
Optimizer: Postgres query optimizer
(16 rows)
explain(locus, costs off) select count(*) from test_131_aoco1, test_131_aoco2 where test_131_aoco1.x = test_131_aoco2.x;
QUERY PLAN
----------------------------------------------------------------------
Finalize Aggregate
Locus: Entry
-> Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Hash Join
Locus: HashedWorkers
Parallel Workers: 2
Hash Cond: (test_131_aoco1.x = test_131_aoco2.x)
-> Parallel Seq Scan on test_131_aoco1
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Hash
Locus: Hashed
-> Parallel Seq Scan on test_131_aoco2
Locus: HashedWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(20 rows)
explain(locus, costs off) select count(*) from test_131_aoco3, test_131_aoco4 where test_131_aoco3.x = test_131_aoco4.x;
QUERY PLAN
----------------------------------------------------------------------
Finalize Aggregate
Locus: Entry
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Partial Aggregate
Locus: Hashed
-> Hash Join
Locus: Hashed
Hash Cond: (test_131_aoco3.x = test_131_aoco4.x)
-> Seq Scan on test_131_aoco3
Locus: Hashed
-> Hash
Locus: Hashed
-> Seq Scan on test_131_aoco4
Locus: Hashed
Optimizer: Postgres query optimizer
(16 rows)
abort;
create table ao1(x int, y int) with(appendonly=true);
create table ao2(x int, y int) with(appendonly=true);
create table aocs1(x int, y int) with(appendonly=true, orientation=column);
begin;
-- encourage use of parallel plans
set local min_parallel_table_scan_size = 0;
set local max_parallel_workers_per_gather = 4;
-- test insert into multiple files even enable_parallel is off.
set local enable_parallel = off;
-- insert multiple segfiles for parallel
set local gp_appendonly_insert_files = 4;
set local gp_appendonly_insert_files_tuples_range = 50000;
-- test appendonly table parallel
insert into ao1 select i, i from generate_series(1, 1200000) g(i);
analyze ao1;
insert into ao2 select i%10, i from generate_series(1, 1200000) g(i);
analyze ao2;
select segfilecount from pg_appendonly where relid = 'ao1'::regclass;
segfilecount
--------------
4
(1 row)
set local enable_parallel = on;
explain(costs off) select count(*) from ao1;
QUERY PLAN
--------------------------------------------------
Finalize Aggregate
-> Gather Motion 12:1 (slice1; segments: 12)
-> Partial Aggregate
-> Parallel Seq Scan on ao1
Optimizer: Postgres query optimizer
(5 rows)
select count(*) from ao1;
count
---------
1200000
(1 row)
-- test aocs table parallel
set local enable_parallel = off;
insert into aocs1 select i, i from generate_series(1, 1200000) g(i);
analyze aocs1;
select segfilecount from pg_appendonly where relid = 'aocs1'::regclass;
segfilecount
--------------
4
(1 row)
set local enable_parallel = on;
explain(costs off) select count(*) from aocs1;
QUERY PLAN
--------------------------------------------------
Finalize Aggregate
-> Gather Motion 12:1 (slice1; segments: 12)
-> Partial Aggregate
-> Parallel Seq Scan on aocs1
Optimizer: Postgres query optimizer
(5 rows)
select count(*) from aocs1;
count
---------
1200000
(1 row)
-- test locus of HashedWorkers can parallel join without motion
explain(locus, costs off) select count(*) from ao1, ao2 where ao1.x = ao2.x;
QUERY PLAN
--------------------------------------------------------
Finalize Aggregate
Locus: Entry
-> Gather Motion 12:1 (slice1; segments: 12)
Locus: Entry
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 4
-> Parallel Hash Join
Locus: HashedWorkers
Parallel Workers: 4
Hash Cond: (ao1.x = ao2.x)
-> Parallel Seq Scan on ao1
Locus: HashedWorkers
Parallel Workers: 4
-> Parallel Hash
Locus: Hashed
-> Parallel Seq Scan on ao2
Locus: HashedWorkers
Parallel Workers: 4
Optimizer: Postgres query optimizer
(20 rows)
select count(*) from ao1, ao2 where ao1.x = ao2.x;
count
---------
1080000
(1 row)
reset enable_parallel;
commit;
--
-- test parallel with indices
--
create index on ao1(y);
create index on aocs1(y);
analyze ao1;
analyze aocs1;
-- test AO/AOCS should not be IndexScan
begin;
set local enable_parallel = on;
set local enable_seqscan = off;
set local enable_indexscan = on;
set local enable_bitmapscan = on;
set local max_parallel_workers_per_gather=1;
explain(costs off) select y from ao1 where y > 1000000;
QUERY PLAN
--------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
-> Bitmap Heap Scan on ao1
Recheck Cond: (y > 1000000)
-> Bitmap Index Scan on ao1_y_idx
Index Cond: (y > 1000000)
Optimizer: Postgres query optimizer
(6 rows)
explain(costs off) select y from aocs1 where y > 1000000;
QUERY PLAN
----------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
-> Bitmap Heap Scan on aocs1
Recheck Cond: (y > 1000000)
-> Bitmap Index Scan on aocs1_y_idx
Index Cond: (y > 1000000)
Optimizer: Postgres query optimizer
(6 rows)
set local max_parallel_workers_per_gather=0;
explain(costs off) select y from ao1 where y > 1000000;
QUERY PLAN
--------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
-> Bitmap Heap Scan on ao1
Recheck Cond: (y > 1000000)
-> Bitmap Index Scan on ao1_y_idx
Index Cond: (y > 1000000)
Optimizer: Postgres query optimizer
(6 rows)
explain(costs off) select y from aocs1 where y > 1000000;
QUERY PLAN
----------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
-> Bitmap Heap Scan on aocs1
Recheck Cond: (y > 1000000)
-> Bitmap Index Scan on aocs1_y_idx
Index Cond: (y > 1000000)
Optimizer: Postgres query optimizer
(6 rows)
commit;
drop table ao1;
drop table ao2;
drop table aocs1;
-- test Parallel Bitmap Heap Scan
begin;
create table t1(c1 int, c2 int) with(parallel_workers=2) distributed by (c1);
set local enable_parallel = on;
create index on t1(c2);
insert into t1 select i, i from generate_series(1, 10000000) i;
analyze t1;
set local force_parallel_mode = 1;
set local enable_seqscan = off;
explain(locus, costs off) select c2 from t1;
QUERY PLAN
------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Parallel Index Only Scan using t1_c2_idx on t1
Locus: HashedWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(6 rows)
-- results check
explain(locus, costs off) select count(c2) from t1;
QUERY PLAN
------------------------------------------------------------------
Finalize Aggregate
Locus: Entry
-> Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Index Only Scan using t1_c2_idx on t1
Locus: HashedWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(11 rows)
select count(c2) from t1;
count
----------
10000000
(1 row)
set local enable_parallel = off;
explain(locus, costs off) select count(c2) from t1;
QUERY PLAN
---------------------------------------------------------
Finalize Aggregate
Locus: Entry
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Partial Aggregate
Locus: Hashed
-> Index Only Scan using t1_c2_idx on t1
Locus: Hashed
Optimizer: Postgres query optimizer
(9 rows)
select count(c2) from t1;
count
----------
10000000
(1 row)
abort;
-- test segfilecount according to data volume.
create table ao_segfilecount(x int, y int) with(appendonly=true);
create table aocs_segfilecount(x int, y int) with(appendonly=true, orientation=column);
begin;
set local gp_appendonly_insert_files = 5;
set local gp_appendonly_insert_files_tuples_range = 10;
-- no enough data, open only one segment file.
insert into ao_segfilecount select i, i from generate_series(1, 29) g(i);
analyze ao_segfilecount;
select segfilecount from pg_appendonly where relid='ao_segfilecount'::regclass;
segfilecount
--------------
1
(1 row)
-- no enough data, open two segment files.
insert into ao_segfilecount select i, i from generate_series(1, 60) g(i);
analyze ao_segfilecount;
select segfilecount from pg_appendonly where relid='ao_segfilecount'::regclass;
segfilecount
--------------
2
(1 row)
-- proper data, open segment file according to GUC.
insert into ao_segfilecount select i, i from generate_series(1, 150) g(i);
analyze ao_segfilecount;
select segfilecount from pg_appendonly where relid='ao_segfilecount'::regclass;
segfilecount
--------------
5
(1 row)
-- excess data, open segment file according to GUC.
insert into ao_segfilecount select i, i from generate_series(1, 200) g(i);
analyze ao_segfilecount;
select segfilecount from pg_appendonly where relid='ao_segfilecount'::regclass;
segfilecount
--------------
5
(1 row)
-- no enough data, open only one segment file.
insert into aocs_segfilecount select i, i from generate_series(1, 29) g(i);
analyze aocs_segfilecount;
select segfilecount from pg_appendonly where relid='aocs_segfilecount'::regclass;
segfilecount
--------------
1
(1 row)
-- no enough data, open two segment files.
insert into aocs_segfilecount select i, i from generate_series(1, 60) g(i);
analyze aocs_segfilecount;
select segfilecount from pg_appendonly where relid='aocs_segfilecount'::regclass;
segfilecount
--------------
2
(1 row)
-- proper data, open segment file according to GUC.
insert into aocs_segfilecount select i, i from generate_series(1, 150) g(i);
analyze aocs_segfilecount;
select segfilecount from pg_appendonly where relid='aocs_segfilecount'::regclass;
segfilecount
--------------
5
(1 row)
-- excess data, open segment file according to GUC.
insert into aocs_segfilecount select i, i from generate_series(1, 200) g(i);
analyze aocs_segfilecount;
select segfilecount from pg_appendonly where relid='aocs_segfilecount'::regclass;
segfilecount
--------------
5
(1 row)
abort;
drop table ao_segfilecount;
drop table aocs_segfilecount;
-- test gp_appendonly_insert_files doesn't take effect
begin;
create table t (x int);
insert into t select i from generate_series(1, 1000) i;
set local gp_appendonly_insert_files=4;
set local gp_appendonly_insert_files_tuples_range = 10;
create table ao1 using ao_row as select * from t;
analyze ao1;
select segfilecount from pg_appendonly where relid='ao1'::regclass;
segfilecount
--------------
1
(1 row)
create table ao2 with(appendonly=true) as select * from t;
analyze ao2;
select segfilecount from pg_appendonly where relid='ao2'::regclass;
segfilecount
--------------
1
(1 row)
create table aocs1 using ao_column as select * from t;
analyze aocs1;
select segfilecount from pg_appendonly where relid='aocs1'::regclass;
segfilecount
--------------
1
(1 row)
create table aocs2 with(appendonly=true, orientation=column) as select * from t;
analyze aocs2;
select segfilecount from pg_appendonly where relid='aocs2'::regclass;
segfilecount
--------------
1
(1 row)
abort;
-- test replicated tables parallel
begin;
set local max_parallel_workers_per_gather = 2;
create table t1(a int, b int) with(parallel_workers=2);
create table rt1(a int, b int) with(parallel_workers=2) distributed replicated;
create table rt2(a int, b int) distributed replicated;
create table rt3(a int, b int) distributed replicated;
insert into t1 select i, i from generate_series(1, 100000) i;
insert into t1 select i, i+1 from generate_series(1, 10) i;
insert into rt1 select i, i+1 from generate_series(1, 10) i;
insert into rt2 select i, i+1 from generate_series(1, 10000) i;
insert into rt3 select i, i+1 from generate_series(1, 10) i;
analyze t1;
analyze rt1;
analyze rt2;
analyze rt3;
-- replica parallel select
set local enable_parallel = off;
explain(locus, costs off) select * from rt1;
QUERY PLAN
------------------------------------------
Gather Motion 1:1 (slice1; segments: 1)
Locus: Entry
-> Seq Scan on rt1
Locus: SegmentGeneral
Optimizer: Postgres query optimizer
(5 rows)
select * from rt1;
a | b
----+----
1 | 2
2 | 3
3 | 4
4 | 5
5 | 6
6 | 7
7 | 8
8 | 9
9 | 10
10 | 11
(10 rows)
set local enable_parallel = on;
explain(locus, costs off) select * from rt1;
QUERY PLAN
------------------------------------------
Gather Motion 2:1 (slice1; segments: 2)
Locus: Entry
-> Parallel Seq Scan on rt1
Locus: SegmentGeneralWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(6 rows)
select * from rt1;
a | b
----+----
1 | 2
2 | 3
3 | 4
4 | 5
5 | 6
6 | 7
7 | 8
8 | 9
9 | 10
10 | 11
(10 rows)
-- replica join replica
set local enable_parallel = off;
select * from rt1 join rt2 on rt2.b = rt1.a;
a | b | a | b
----+----+---+----
2 | 3 | 1 | 2
3 | 4 | 2 | 3
4 | 5 | 3 | 4
5 | 6 | 4 | 5
6 | 7 | 5 | 6
7 | 8 | 6 | 7
8 | 9 | 7 | 8
9 | 10 | 8 | 9
10 | 11 | 9 | 10
(9 rows)
set local enable_parallel = on;
explain(locus, costs off) select * from rt1 join rt2 on rt2.b = rt1.a;
QUERY PLAN
-------------------------------------------
Gather Motion 1:1 (slice1; segments: 1)
Locus: Entry
-> Hash Join
Locus: SegmentGeneral
Hash Cond: (rt2.b = rt1.a)
-> Seq Scan on rt2
Locus: SegmentGeneral
-> Hash
Locus: SegmentGeneral
-> Seq Scan on rt1
Locus: SegmentGeneral
Optimizer: Postgres query optimizer
(12 rows)
select * from rt1 join rt2 on rt2.b = rt1.a;
a | b | a | b
----+----+---+----
2 | 3 | 1 | 2
3 | 4 | 2 | 3
4 | 5 | 3 | 4
5 | 6 | 4 | 5
6 | 7 | 5 | 6
7 | 8 | 6 | 7
8 | 9 | 7 | 8
9 | 10 | 8 | 9
10 | 11 | 9 | 10
(9 rows)
--
-- ex 5_P_5_5
-- SegmentGeneralWorkers parallel join SegmentGeneralWorkers when parallel_aware generate SegmentGeneralWorerks locus.
--
set local min_parallel_table_scan_size = 0;
explain(locus, costs off) select * from rt1 join rt2 on rt2.b = rt1.a;
QUERY PLAN
--------------------------------------------------
Gather Motion 2:1 (slice1; segments: 2)
Locus: Entry
-> Parallel Hash Join
Locus: SegmentGeneralWorkers
Parallel Workers: 2
Hash Cond: (rt2.b = rt1.a)
-> Parallel Seq Scan on rt2
Locus: SegmentGeneralWorkers
Parallel Workers: 2
-> Parallel Hash
Locus: SegmentGeneral
-> Parallel Seq Scan on rt1
Locus: SegmentGeneralWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(15 rows)
select * from rt1 join rt2 on rt2.b = rt1.a;
a | b | a | b
----+----+---+----
2 | 3 | 1 | 2
3 | 4 | 2 | 3
4 | 5 | 3 | 4
5 | 6 | 4 | 5
6 | 7 | 5 | 6
7 | 8 | 6 | 7
8 | 9 | 7 | 8
9 | 10 | 8 | 9
10 | 11 | 9 | 10
(9 rows)
--
-- ex 5_4_5
-- SegmentGeneralWorkers parallel join SegmentGeneral generate SegmentGeneralWorkers locus.
--
set local enable_parallel_hash = off;
explain(locus, costs off) select * from rt1 join rt2 on rt2.b = rt1.a;
QUERY PLAN
--------------------------------------------
Gather Motion 2:1 (slice1; segments: 2)
Locus: Entry
-> Hash Join
Locus: SegmentGeneralWorkers
Parallel Workers: 2
Hash Cond: (rt2.b = rt1.a)
-> Parallel Seq Scan on rt2
Locus: SegmentGeneralWorkers
Parallel Workers: 2
-> Hash
Locus: SegmentGeneral
-> Seq Scan on rt1
Locus: SegmentGeneral
Optimizer: Postgres query optimizer
(14 rows)
select * from rt1 join rt2 on rt2.b = rt1.a;
a | b | a | b
----+----+---+----
2 | 3 | 1 | 2
3 | 4 | 2 | 3
4 | 5 | 3 | 4
5 | 6 | 4 | 5
6 | 7 | 5 | 6
7 | 8 | 6 | 7
8 | 9 | 7 | 8
9 | 10 | 8 | 9
10 | 11 | 9 | 10
(9 rows)
--
-- t1 join rt1 join rt2
--
set local enable_parallel = off;
explain(locus, costs off) select * from rt1 join t1 on rt1.a = t1.b join rt2 on rt2.a = t1.b;
QUERY PLAN
-------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Hash Join
Locus: Hashed
Hash Cond: (t1.b = rt1.a)
-> Seq Scan on t1
Locus: Hashed
-> Hash
Locus: SegmentGeneral
-> Hash Join
Locus: SegmentGeneral
Hash Cond: (rt2.a = rt1.a)
-> Seq Scan on rt2
Locus: SegmentGeneral
-> Hash
Locus: SegmentGeneral
-> Seq Scan on rt1
Locus: SegmentGeneral
Optimizer: Postgres query optimizer
(19 rows)
select * from rt1 join t1 on rt1.a = t1.b join rt2 on rt2.a = t1.b;
a | b | a | b | a | b
----+----+----+----+----+----
2 | 3 | 2 | 2 | 2 | 3
3 | 4 | 3 | 3 | 3 | 4
4 | 5 | 4 | 4 | 4 | 5
7 | 8 | 7 | 7 | 7 | 8
8 | 9 | 8 | 8 | 8 | 9
3 | 4 | 2 | 3 | 3 | 4
4 | 5 | 3 | 4 | 4 | 5
5 | 6 | 4 | 5 | 5 | 6
8 | 9 | 7 | 8 | 8 | 9
9 | 10 | 8 | 9 | 9 | 10
5 | 6 | 5 | 5 | 5 | 6
6 | 7 | 6 | 6 | 6 | 7
9 | 10 | 9 | 9 | 9 | 10
10 | 11 | 10 | 10 | 10 | 11
6 | 7 | 5 | 6 | 6 | 7
7 | 8 | 6 | 7 | 7 | 8
10 | 11 | 9 | 10 | 10 | 11
1 | 2 | 1 | 1 | 1 | 2
2 | 3 | 1 | 2 | 2 | 3
(19 rows)
-- parallel hash join
set local enable_parallel = on;
set local enable_parallel_hash = on;
--
-- SegmentGeneralWorkers parallel join HashedWorkers when parallel_aware generate HashedWorkers.
-- ex 12_P_5_12
-- HashedWorkers parallel join SegmentGeneralWorkers when parallel_aware generate HashedWorkers.
--
explain(locus, costs off) select * from rt1 join t1 on rt1.a = t1.b join rt2 on rt2.a = t1.b;
QUERY PLAN
--------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Parallel Hash Join
Locus: HashedWorkers
Parallel Workers: 2
Hash Cond: (rt2.a = rt1.a)
-> Parallel Seq Scan on rt2
Locus: SegmentGeneralWorkers
Parallel Workers: 2
-> Parallel Hash
Locus: Hashed
-> Parallel Hash Join
Locus: HashedWorkers
Parallel Workers: 2
Hash Cond: (t1.b = rt1.a)
-> Parallel Seq Scan on t1
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Hash
Locus: SegmentGeneral
-> Parallel Seq Scan on rt1
Locus: SegmentGeneralWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(24 rows)
select * from rt1 join t1 on rt1.a = t1.b join rt2 on rt2.a = t1.b;
a | b | a | b | a | b
----+----+----+----+----+----
5 | 6 | 5 | 5 | 5 | 6
6 | 7 | 5 | 6 | 6 | 7
6 | 7 | 6 | 6 | 6 | 7
7 | 8 | 6 | 7 | 7 | 8
9 | 10 | 9 | 9 | 9 | 10
10 | 11 | 9 | 10 | 10 | 11
10 | 11 | 10 | 10 | 10 | 11
2 | 3 | 2 | 2 | 2 | 3
3 | 4 | 2 | 3 | 3 | 4
3 | 4 | 3 | 3 | 3 | 4
4 | 5 | 3 | 4 | 4 | 5
4 | 5 | 4 | 4 | 4 | 5
5 | 6 | 4 | 5 | 5 | 6
7 | 8 | 7 | 7 | 7 | 8
8 | 9 | 7 | 8 | 8 | 9
8 | 9 | 8 | 8 | 8 | 9
9 | 10 | 8 | 9 | 9 | 10
1 | 2 | 1 | 1 | 1 | 2
2 | 3 | 1 | 2 | 2 | 3
(19 rows)
--
-- t1 join rt1 join rt3
--
set local enable_parallel = off;
explain(locus, costs off) select * from rt1 join t1 on rt1.a = t1.b join rt3 on rt3.a = t1.b;
QUERY PLAN
-------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Hash Join
Locus: Hashed
Hash Cond: (t1.b = rt1.a)
-> Hash Join
Locus: Hashed
Hash Cond: (t1.b = rt3.a)
-> Seq Scan on t1
Locus: Hashed
-> Hash
Locus: SegmentGeneral
-> Seq Scan on rt3
Locus: SegmentGeneral
-> Hash
Locus: SegmentGeneral
-> Seq Scan on rt1
Locus: SegmentGeneral
Optimizer: Postgres query optimizer
(19 rows)
select * from rt1 join t1 on rt1.a = t1.b join rt3 on rt3.a = t1.b;
a | b | a | b | a | b
----+----+----+----+----+----
2 | 3 | 2 | 2 | 2 | 3
3 | 4 | 3 | 3 | 3 | 4
4 | 5 | 4 | 4 | 4 | 5
7 | 8 | 7 | 7 | 7 | 8
8 | 9 | 8 | 8 | 8 | 9
3 | 4 | 2 | 3 | 3 | 4
4 | 5 | 3 | 4 | 4 | 5
5 | 6 | 4 | 5 | 5 | 6
8 | 9 | 7 | 8 | 8 | 9
9 | 10 | 8 | 9 | 9 | 10
1 | 2 | 1 | 1 | 1 | 2
2 | 3 | 1 | 2 | 2 | 3
5 | 6 | 5 | 5 | 5 | 6
6 | 7 | 6 | 6 | 6 | 7
9 | 10 | 9 | 9 | 9 | 10
10 | 11 | 10 | 10 | 10 | 11
6 | 7 | 5 | 6 | 6 | 7
7 | 8 | 6 | 7 | 7 | 8
10 | 11 | 9 | 10 | 10 | 11
(19 rows)
-- parallel join without parallel hash
set local enable_parallel = on;
set local enable_parallel_hash = off;
-- HashedWorkers parallel join SegmentGeneral generate HashedWorkers.
explain(locus, costs off) select * from rt1 join t1 on rt1.a = t1.b join rt3 on rt3.a = t1.b;
QUERY PLAN
-------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Hash Join
Locus: HashedWorkers
Parallel Workers: 2
Hash Cond: (t1.b = rt1.a)
-> Hash Join
Locus: HashedWorkers
Parallel Workers: 2
Hash Cond: (t1.b = rt3.a)
-> Parallel Seq Scan on t1
Locus: HashedWorkers
Parallel Workers: 2
-> Hash
Locus: SegmentGeneral
-> Seq Scan on rt3
Locus: SegmentGeneral
-> Hash
Locus: SegmentGeneral
-> Seq Scan on rt1
Locus: SegmentGeneral
Optimizer: Postgres query optimizer
(22 rows)
select * from rt1 join t1 on rt1.a = t1.b join rt3 on rt3.a = t1.b;
a | b | a | b | a | b
----+----+----+----+----+----
1 | 2 | 1 | 1 | 1 | 2
2 | 3 | 1 | 2 | 2 | 3
5 | 6 | 5 | 5 | 5 | 6
6 | 7 | 6 | 6 | 6 | 7
9 | 10 | 9 | 9 | 9 | 10
10 | 11 | 10 | 10 | 10 | 11
6 | 7 | 5 | 6 | 6 | 7
7 | 8 | 6 | 7 | 7 | 8
10 | 11 | 9 | 10 | 10 | 11
2 | 3 | 2 | 2 | 2 | 3
3 | 4 | 3 | 3 | 3 | 4
4 | 5 | 4 | 4 | 4 | 5
7 | 8 | 7 | 7 | 7 | 8
8 | 9 | 8 | 8 | 8 | 9
3 | 4 | 2 | 3 | 3 | 4
4 | 5 | 3 | 4 | 4 | 5
5 | 6 | 4 | 5 | 5 | 6
8 | 9 | 7 | 8 | 8 | 9
9 | 10 | 8 | 9 | 9 | 10
(19 rows)
create table t2(a int, b int) with(parallel_workers=0);
create table rt4(a int, b int) with(parallel_workers=2) distributed replicated;
insert into t2 select i, i+1 from generate_series(1, 10) i;
insert into rt4 select i, i+1 from generate_series(1, 10000) i;
analyze t2;
analyze rt4;
set local enable_parallel = off;
select * from rt4 join t2 using(b);
b | a | a
----+----+----
2 | 1 | 1
6 | 5 | 5
7 | 6 | 6
10 | 9 | 9
11 | 10 | 10
3 | 2 | 2
4 | 3 | 3
5 | 4 | 4
8 | 7 | 7
9 | 8 | 8
(10 rows)
set local enable_parallel = on;
set local enable_parallel_hash = off;
--
-- ex 5_9_12
-- SegmentGeneralWorkers(w=N) parallel join Hashed(W=0) generate HashedWorkers(w=N).
--
explain(locus, costs off) select * from rt4 join t2 using(b);
QUERY PLAN
--------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Hash Join
Locus: HashedWorkers
Parallel Workers: 2
Hash Cond: (rt4.b = t2.b)
-> Parallel Seq Scan on rt4
Locus: SegmentGeneralWorkers
Parallel Workers: 2
-> Hash
Locus: Hashed
-> Seq Scan on t2
Locus: Hashed
Optimizer: Postgres query optimizer
(14 rows)
select * from rt4 join t2 using(b);
b | a | a
----+----+----
2 | 1 | 1
3 | 2 | 2
4 | 3 | 3
5 | 4 | 4
8 | 7 | 7
9 | 8 | 8
6 | 5 | 5
7 | 6 | 6
10 | 9 | 9
11 | 10 | 10
(10 rows)
create table t3(a int, b int) with(parallel_workers=2);
insert into t3 select i, i+1 from generate_series(1, 9000) i;
analyze t3;
set local enable_parallel = off;
select count(*) from rt4 join t3 using(b);
count
-------
9000
(1 row)
set local enable_parallel = on;
set local enable_parallel_hash = on;
--
-- ex 5_P_12_12
-- SegmentGeneralWorkers parallel join HashedWorkers when parallel_aware generate HashedWorkers.
--
explain(locus, costs off) select * from rt4 join t3 using(b);
QUERY PLAN
--------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Parallel Hash Join
Locus: HashedWorkers
Parallel Workers: 2
Hash Cond: (rt4.b = t3.b)
-> Parallel Seq Scan on rt4
Locus: SegmentGeneralWorkers
Parallel Workers: 2
-> Parallel Hash
Locus: Hashed
-> Parallel Seq Scan on t3
Locus: HashedWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(15 rows)
select count(*) from rt4 join t3 using(b);
count
-------
9000
(1 row)
abort;
--
-- ex 5_11_11
-- SegmentGeneralWorkers(workers=N) join Strewn(worker=0) without shared hash table.
-- Join locus: Strewn(worker=N).
--
begin;
create table t_replica_workers_2(a int, b int) with(parallel_workers=2) distributed replicated;
insert into t_replica_workers_2 select i, i+1 from generate_series(1, 10) i;
analyze t_replica_workers_2;
create table t_random_workers_0(a int, b int) with(parallel_workers=0) distributed randomly;
insert into t_random_workers_0 select i, i+1 from generate_series(1, 5) i;
analyze t_random_workers_0;
set local enable_parallel= true;
set local enable_parallel_hash= false;
explain(locus, costs off) select * from t_replica_workers_2 join t_random_workers_0 using(a);
QUERY PLAN
-------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Hash Join
Locus: Strewn
Parallel Workers: 2
Hash Cond: (t_replica_workers_2.a = t_random_workers_0.a)
-> Parallel Seq Scan on t_replica_workers_2
Locus: SegmentGeneralWorkers
Parallel Workers: 2
-> Hash
Locus: Strewn
-> Seq Scan on t_random_workers_0
Locus: Strewn
Optimizer: Postgres query optimizer
(14 rows)
select * from t_replica_workers_2 join t_random_workers_0 using(a);
a | b | b
---+---+---
2 | 3 | 3
3 | 4 | 4
1 | 2 | 2
4 | 5 | 5
5 | 6 | 6
(5 rows)
-- non parallel results
set local enable_parallel=false;
select * from t_replica_workers_2 join t_random_workers_0 using(a);
a | b | b
---+---+---
2 | 3 | 3
3 | 4 | 4
1 | 2 | 2
4 | 5 | 5
5 | 6 | 6
(5 rows)
abort;
--
-- ex 11_P_5_11
-- Strewn(worker=N) join SegmentGeneralWorkers(workers=N) with shared hash table.
-- Join locus: Strewn(worker=N).
--
begin;
create table t_replica_workers_2(a int, b int) with(parallel_workers=2) distributed replicated;
insert into t_replica_workers_2 select i, i+1 from generate_series(1, 10) i;
analyze t_replica_workers_2;
create table t_random_workers_2(a int, b int) with(parallel_workers=2) distributed randomly;
insert into t_random_workers_2 select i, i+1 from generate_series(1, 5) i;
analyze t_random_workers_2;
set local enable_parallel= true;
set local enable_parallel_hash= true;
explain(locus, costs off) select * from t_replica_workers_2 right join t_random_workers_2 using(a);
QUERY PLAN
-------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Parallel Hash Left Join
Locus: Strewn
Parallel Workers: 2
Hash Cond: (t_random_workers_2.a = t_replica_workers_2.a)
-> Parallel Seq Scan on t_random_workers_2
Locus: Strewn
Parallel Workers: 2
-> Parallel Hash
Locus: SegmentGeneral
-> Parallel Seq Scan on t_replica_workers_2
Locus: SegmentGeneralWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(15 rows)
select * from t_replica_workers_2 right join t_random_workers_2 using(a);
a | b | b
---+---+---
5 | 6 | 6
1 | 2 | 2
2 | 3 | 3
3 | 4 | 4
4 | 5 | 5
(5 rows)
-- non parallel results
set local enable_parallel=false;
select * from t_replica_workers_2 right join t_random_workers_2 using(a);
a | b | b
---+---+---
1 | 2 | 2
2 | 3 | 3
3 | 4 | 4
4 | 5 | 5
5 | 6 | 6
(5 rows)
abort;
--
-- ex 5_P_11_11
-- SegmentGeneralWorkers(workers=N) join Strewn(workers=N) with shared hash table.
-- Join locus: Strewn(workers=N).
--
begin;
create table t_replica_workers_2(a int, b int) with(parallel_workers=2) distributed replicated;
insert into t_replica_workers_2 select i, i+1 from generate_series(1, 10) i;
analyze t_replica_workers_2;
create table t_random_workers_2(a int, b int) with(parallel_workers=2) distributed randomly;
insert into t_random_workers_2 select i, i+1 from generate_series(1, 5) i;
analyze t_random_workers_2;
set local enable_parallel= true;
set local enable_parallel_hash= true;
explain(locus, costs off) select * from t_replica_workers_2 join t_random_workers_2 using(a);
QUERY PLAN
-------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Parallel Hash Join
Locus: Strewn
Parallel Workers: 2
Hash Cond: (t_replica_workers_2.a = t_random_workers_2.a)
-> Parallel Seq Scan on t_replica_workers_2
Locus: SegmentGeneralWorkers
Parallel Workers: 2
-> Parallel Hash
Locus: Strewn
-> Parallel Seq Scan on t_random_workers_2
Locus: Strewn
Parallel Workers: 2
Optimizer: Postgres query optimizer
(16 rows)
select * from t_replica_workers_2 join t_random_workers_2 using(a);
a | b | b
---+---+---
2 | 3 | 3
1 | 2 | 2
3 | 4 | 4
4 | 5 | 5
5 | 6 | 6
(5 rows)
-- non parallel results
set local enable_parallel=false;
select * from t_replica_workers_2 join t_random_workers_2 using(a);
a | b | b
---+---+---
2 | 3 | 3
1 | 2 | 2
3 | 4 | 4
4 | 5 | 5
5 | 6 | 6
(5 rows)
abort;
--
-- ex 2_P_5_2
-- SingleQE join SegmentGeneralWorkers.
-- Join locus: SingleQE(may be elided to Entry).
--
begin;
create table t1(a int, b int) with(parallel_workers=2);
create table rt1(a int, b int) with(parallel_workers=2) distributed replicated;
insert into t1 select i, i from generate_series(1, 100000) i;
insert into rt1 select i, i+1 from generate_series(1, 10000) i;
analyze t1;
analyze rt1;
set local enable_parallel = on;
explain(locus, costs off) select * from (select count(*) as a from t1) t1 left join rt1 on rt1.a = t1.a;
QUERY PLAN
------------------------------------------------------
Parallel Hash Left Join
Locus: Entry
Hash Cond: ((count(*)) = rt1.a)
-> Finalize Aggregate
Locus: Entry
-> Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Seq Scan on t1
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Hash
Locus: Entry
-> Gather Motion 2:1 (slice2; segments: 2)
Locus: Entry
-> Parallel Seq Scan on rt1
Locus: SegmentGeneralWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(21 rows)
select * from (select count(*) as a from t1) t1 left join rt1 on rt1.a = t1.a;
a | a | b
--------+---+---
100000 | |
(1 row)
set local enable_parallel = off;
select * from (select count(*) as a from t1) t1 left join rt1 on rt1.a = t1.a;
a | a | b
--------+---+---
100000 | |
(1 row)
abort;
--
-- ex 5_P_2_2
-- SingleQE join SegmentGeneralWorkers.
-- Join locus: SingleQE(may be elided to Entry).
--
begin;
set local enable_parallel = on;
set local max_parallel_workers_per_gather = 4;
create table t1(a int, b int) with(parallel_workers=4);
create table t2(a int, b int) with(parallel_workers=4);
create table rt1(a int, b int) with(parallel_workers=4) distributed replicated;
insert into t1 select i, i from generate_series(1, 10000000) i;
insert into t2 select i, i from generate_series(1, 10000000) i;
insert into rt1 select i, i+1 from generate_series(1, 10000) i;
analyze t1;
analyze t2;
analyze rt1;
explain(costs off, locus) select * from rt1 join (select count(*) as c, sum(t1.a) as a from t1 join t2 using(a)) t3 on t3.c = rt1.a;
QUERY PLAN
-------------------------------------------------------------------
Parallel Hash Join
Locus: Entry
Hash Cond: (rt1.a = (count(*)))
-> Gather Motion 4:1 (slice1; segments: 4)
Locus: Entry
-> Parallel Seq Scan on rt1
Locus: SegmentGeneralWorkers
Parallel Workers: 4
-> Parallel Hash
Locus: Entry
-> Finalize Aggregate
Locus: Entry
-> Gather Motion 12:1 (slice2; segments: 12)
Locus: Entry
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 4
-> Parallel Hash Join
Locus: HashedWorkers
Parallel Workers: 4
Hash Cond: (t1.a = t2.a)
-> Parallel Seq Scan on t1
Locus: HashedWorkers
Parallel Workers: 4
-> Parallel Hash
Locus: Hashed
-> Parallel Seq Scan on t2
Locus: HashedWorkers
Parallel Workers: 4
Optimizer: Postgres query optimizer
(30 rows)
select * from rt1 join (select count(*) as c, sum(t1.a) as a from t1 join t2 using(a)) t3 on t3.c = rt1.a;
a | b | c | a
---+---+---+---
(0 rows)
set local enable_parallel = off;
explain(costs off, locus) select * from rt1 join (select count(*) as c, sum(t1.a) as a from t1 join t2 using(a)) t3 on t3.c = rt1.a;
QUERY PLAN
------------------------------------------------------------
Hash Join
Locus: Entry
Hash Cond: (rt1.a = (count(*)))
-> Gather Motion 1:1 (slice1; segments: 1)
Locus: Entry
-> Seq Scan on rt1
Locus: SegmentGeneral
-> Hash
Locus: Entry
-> Finalize Aggregate
Locus: Entry
-> Gather Motion 3:1 (slice2; segments: 3)
Locus: Entry
-> Partial Aggregate
Locus: Hashed
-> Hash Join
Locus: Hashed
Hash Cond: (t1.a = t2.a)
-> Seq Scan on t1
Locus: Hashed
-> Hash
Locus: Hashed
-> Seq Scan on t2
Locus: Hashed
Optimizer: Postgres query optimizer
(25 rows)
select * from rt1 join (select count(*) as c, sum(t1.a) as a from t1 join t2 using(a)) t3 on t3.c = rt1.a;
a | b | c | a
---+---+---+---
(0 rows)
abort;
--
-- Test final join path's parallel_workers should be same with join_locus whose
-- parallel_workers is different from origin outer path(without motion).
--
begin;
create table t1(a int, b int) with(parallel_workers=3);
create table t2(b int, a int) with(parallel_workers=2);
insert into t1 select i, i+1 from generate_series(1, 10) i;
insert into t2 select i, i+1 from generate_series(1, 5) i;
analyze t1;
analyze t2;
set local optimizer=off;
set local enable_parallel=on;
set local max_parallel_workers_per_gather= 4;
explain(costs off) select * from t1 right join t2 on t1.b = t2.a;
QUERY PLAN
------------------------------------------------------------------
Gather Motion 9:1 (slice1; segments: 9)
-> Parallel Hash Left Join
Hash Cond: (t2.a = t1.b)
-> Redistribute Motion 6:9 (slice2; segments: 6)
Hash Key: t2.a
Hash Module: 3
-> Parallel Seq Scan on t2
-> Parallel Hash
-> Redistribute Motion 9:9 (slice3; segments: 9)
Hash Key: t1.b
Hash Module: 3
-> Parallel Seq Scan on t1
Optimizer: Postgres query optimizer
(13 rows)
abort;
--
-- Test SingleQE locus could particapte in parallel plan.
--
begin;
create table t1(a int, b int) with(parallel_workers=2);
create table t2(a int, b int) with(parallel_workers=2);
insert into t1 select i%10, i from generate_series(1, 5) i;
insert into t1 values (100000);
insert into t2 select i%10, i from generate_series(1, 100000) i;
analyze t1;
analyze t2;
set local enable_parallel = on;
-- parallel hash join with shared table, SinglQE as outer partial path.
explain(locus, costs off) select * from (select count(*) as a from t2) t2 left join t1 on t1.a = t2.a;
QUERY PLAN
------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Parallel Hash Left Join
Locus: Hashed
Parallel Workers: 2
Hash Cond: ((count(*)) = t1.a)
-> Redistribute Motion 1:6 (slice2; segments: 1)
Locus: Hashed
Parallel Workers: 2
Hash Key: (count(*))
Hash Module: 3
-> Finalize Aggregate
Locus: SingleQE
-> Gather Motion 6:1 (slice3; segments: 6)
Locus: SingleQE
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Seq Scan on t2
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Hash
Locus: Hashed
-> Parallel Seq Scan on t1
Locus: HashedWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(27 rows)
select * from (select count(*) as a from t2) t2 left join t1 on t1.a = t2.a;
a | a | b
--------+--------+---
100000 | 100000 |
(1 row)
set local enable_parallel = off;
select * from (select count(*) as a from t2) t2 left join t1 on t1.a = t2.a;
a | a | b
--------+--------+---
100000 | 100000 |
(1 row)
set local enable_parallel = on;
-- parallel hash join with shared table, SinglQE as inner partial path.
explain(locus, costs off) select * from t1 join (select count(*) as a from t2) t2 on t1.a = t2.a;
QUERY PLAN
------------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
-> Parallel Hash Join
Locus: HashedWorkers
Parallel Workers: 2
Hash Cond: (t1.a = (count(*)))
-> Parallel Seq Scan on t1
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Hash
Locus: Hashed
-> Redistribute Motion 1:6 (slice2; segments: 1)
Locus: Hashed
Parallel Workers: 2
Hash Key: (count(*))
Hash Module: 3
-> Finalize Aggregate
Locus: SingleQE
-> Gather Motion 6:1 (slice3; segments: 6)
Locus: SingleQE
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Seq Scan on t2
Locus: HashedWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(27 rows)
select * from t1 join (select count(*) as a from t2) t2 on t1.a = t2.a;
a | b | a
--------+---+--------
100000 | | 100000
(1 row)
set local enable_parallel = off;
select * from t1 join (select count(*) as a from t2) t2 on t1.a = t2.a;
a | b | a
--------+---+--------
100000 | | 100000
(1 row)
set local enable_parallel = on;
-- parallel hash join without shared table.
set local enable_parallel_hash = off;
explain(locus, costs off) select * from t1 join (select count(*) as a from t2) t2 on t1.a = t2.a;
QUERY PLAN
------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Hash Join
Locus: Hashed
Hash Cond: ((count(*)) = t1.a)
-> Redistribute Motion 1:3 (slice2; segments: 1)
Locus: Hashed
Hash Key: (count(*))
-> Finalize Aggregate
Locus: SingleQE
-> Gather Motion 6:1 (slice3; segments: 6)
Locus: SingleQE
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Seq Scan on t2
Locus: HashedWorkers
Parallel Workers: 2
-> Hash
Locus: Hashed
-> Seq Scan on t1
Locus: Hashed
Optimizer: Postgres query optimizer
(23 rows)
select * from t1 join (select count(*) as a from t2) t2 on t1.a = t2.a;
a | b | a
--------+---+--------
100000 | | 100000
(1 row)
-- parallel merge join
set local enable_hashjoin = off;
explain(locus, costs off) select * from t1 join (select count(*) as a from t2) t2 on t1.a = t2.a;
QUERY PLAN
------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Merge Join
Locus: Hashed
Merge Cond: ((count(*)) = t1.a)
-> Sort
Locus: Hashed
Sort Key: (count(*))
-> Redistribute Motion 1:3 (slice2; segments: 1)
Locus: Hashed
Hash Key: (count(*))
-> Finalize Aggregate
Locus: SingleQE
-> Gather Motion 6:1 (slice3; segments: 6)
Locus: SingleQE
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Seq Scan on t2
Locus: HashedWorkers
Parallel Workers: 2
-> Sort
Locus: Hashed
Sort Key: t1.a
-> Seq Scan on t1
Locus: Hashed
Optimizer: Postgres query optimizer
(27 rows)
select * from t1 join (select count(*) as a from t2) t2 on t1.a = t2.a;
a | b | a
--------+---+--------
100000 | | 100000
(1 row)
-- parallel nestloop join
set local enable_mergejoin = off;
set local enable_nestloop = on;
explain(locus, costs off) select * from t1 join (select count(*) as a from t2) t2 on t1.a = t2.a;
QUERY PLAN
------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Nested Loop
Locus: Hashed
Join Filter: (t1.a = (count(*)))
-> Redistribute Motion 1:3 (slice2; segments: 1)
Locus: Hashed
Hash Key: (count(*))
-> Finalize Aggregate
Locus: SingleQE
-> Gather Motion 6:1 (slice3; segments: 6)
Locus: SingleQE
-> Partial Aggregate
Locus: HashedWorkers
Parallel Workers: 2
-> Parallel Seq Scan on t2
Locus: HashedWorkers
Parallel Workers: 2
-> Seq Scan on t1
Locus: Hashed
Optimizer: Postgres query optimizer
(21 rows)
select * from t1 join (select count(*) as a from t2) t2 on t1.a = t2.a;
a | b | a
--------+---+--------
100000 | | 100000
(1 row)
-- non-parallel results
set local enable_parallel = off;
select * from t1 join (select count(*) as a from t2) t2 on t1.a = t2.a;
a | b | a
--------+---+--------
100000 | | 100000
(1 row)
abort;
begin;
-- use rt1 to generate locus of SegmentGeneralWorkers
-- use rt2 to generate locus of SegmentGeneral
-- use t1 to generate locus of HashedWorkers
-- use t2 to generate locus of Hahsed
-- use pg_class to generate locus of Entry
-- use generate_series(1, 1000) to generate locus of General
-- use select count(*) as a from sq1 to generate locus of SingleQE
create table rt1(a int, b int) distributed replicated;
create table rt2(a int, b int) with (parallel_workers = 0) distributed replicated;
create table t1(a int, b int);
create table t2(a int, b int) with (parallel_workers = 0);
insert into t1 select i, i+1 from generate_series(1, 10000) i;
insert into t2 select i, i+1 from generate_series(1, 10000) i;
insert into rt1 select i, i+1 from generate_series(1, 10000) i;
insert into rt2 select i, i+1 from generate_series(1, 10000) i;
CREATE TABLE sq1 AS SELECT a, b FROM t1 WHERE gp_segment_id = 0;
set local optimizer=off;
set local enable_parallel=on;
set local min_parallel_table_scan_size to 0;
set local max_parallel_workers_per_gather= 4;
analyze rt1;
analyze rt2;
analyze t1;
analyze t2;
analyze sq1;
-- SegmentGeneralWorkers + SegmengGeneralWorkers = SegmentGeneralWorkers
explain (locus, costs off) select * from rt1 union all select * from rt1;
QUERY PLAN
--------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Parallel Append
Locus: SegmentGeneralWorkers
Parallel Workers: 3
-> Parallel Seq Scan on rt1
Locus: SegmentGeneralWorkers
Parallel Workers: 3
-> Parallel Seq Scan on rt1 rt1_1
Locus: SegmentGeneralWorkers
Parallel Workers: 3
Optimizer: Postgres query optimizer
(12 rows)
-- SegmentGeneralWorkers + SegmentGeneral = SegmentGeneralWorkers
explain (locus, costs off) select * from rt1 union all select * from rt2;
QUERY PLAN
--------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Parallel Append
Locus: SegmentGeneralWorkers
Parallel Workers: 3
-> Seq Scan on rt2
Locus: SegmentGeneral
-> Parallel Seq Scan on rt1
Locus: SegmentGeneralWorkers
Parallel Workers: 3
Optimizer: Postgres query optimizer
(11 rows)
-- SegmentGeneralWorkers (Converted to Strewn, Limited on One Segment) + HashedWorkers = Strewn
explain (locus, costs off) select * from rt1 union all select * from t1;
QUERY PLAN
-------------------------------------------------------------
Gather Motion 9:1 (slice1; segments: 9)
Locus: Entry
-> Parallel Append
Locus: Strewn
Parallel Workers: 3
-> Result
Locus: Strewn
Parallel Workers: 3
One-Time Filter: (gp_execution_segment() = 0)
-> Parallel Seq Scan on rt1
Locus: SegmentGeneralWorkers
Parallel Workers: 3
-> Parallel Seq Scan on t1
Locus: HashedWorkers
Parallel Workers: 3
Optimizer: Postgres query optimizer
(16 rows)
-- SegmentGeneralWorkers (Converted to Strewn, Limited on One Segment) + Hashed = Strewn
explain (locus, costs off) select * from rt1 union all select * from t2;
QUERY PLAN
-------------------------------------------------------------
Gather Motion 9:1 (slice1; segments: 9)
Locus: Entry
-> Parallel Append
Locus: Strewn
Parallel Workers: 3
-> Seq Scan on t2
Locus: Hashed
-> Result
Locus: Strewn
Parallel Workers: 3
One-Time Filter: (gp_execution_segment() = 0)
-> Parallel Seq Scan on rt1
Locus: SegmentGeneralWorkers
Parallel Workers: 3
Optimizer: Postgres query optimizer
(15 rows)
-- SingleQE as subquery seems cannot produce partial_pathlist and don't have chance to parallel append.
explain (locus, costs off) select a from rt1 union all select count(*) as a from sq1;
QUERY PLAN
------------------------------------------------------
Append
Locus: Entry
-> Gather Motion 1:1 (slice1; segments: 1)
Locus: Entry
-> Subquery Scan on "*SELECT* 1"
Locus: SegmentGeneral
-> Seq Scan on rt1
Locus: SegmentGeneral
-> Finalize Aggregate
Locus: Entry
-> Gather Motion 3:1 (slice2; segments: 3)
Locus: Entry
-> Partial Aggregate
Locus: Hashed
-> Seq Scan on sq1
Locus: Hashed
Optimizer: Postgres query optimizer
(17 rows)
-- SegmentGeneralWorkers + General = SegmentGeneralWorkers
explain (locus, costs off) select a from rt1 union all select a from generate_series(1, 1000) a;
QUERY PLAN
------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Parallel Append
Locus: SegmentGeneralWorkers
Parallel Workers: 3
-> Function Scan on generate_series a
Locus: General
-> Parallel Seq Scan on rt1
Locus: SegmentGeneralWorkers
Parallel Workers: 3
Optimizer: Postgres query optimizer
(11 rows)
-- Entry as subquery seems cannot produce partial_pathlist and don't have chance to parallel append.
-- flaky case failed: expected use seqscan on pg_class but choose indexscan sometimes.
set local enable_indexscan = off;
set local enable_indexonlyscan = off;
explain (locus, costs off) select a from rt1 union all select oid as a from pg_class;
QUERY PLAN
------------------------------------------------
Append
Locus: Entry
-> Gather Motion 1:1 (slice1; segments: 1)
Locus: Entry
-> Subquery Scan on "*SELECT* 1"
Locus: SegmentGeneral
-> Seq Scan on rt1
Locus: SegmentGeneral
-> Seq Scan on pg_class
Locus: Entry
Optimizer: Postgres query optimizer
(11 rows)
abort;
--
-- Test two-phase parallel Limit
--
begin;
create table t1(c1 int, c2 int) with(parallel_workers=2);
insert into t1 select i, i+1 from generate_series(1, 100000) i;
analyze t1;
set local optimizer = off;
set local enable_parallel = on;
explain(costs off, locus) select * from t1 order by c2 asc limit 3 offset 5;
QUERY PLAN
-------------------------------------------------
Limit
Locus: Entry
-> Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
Merge Key: c2
-> Limit
Locus: HashedWorkers
Parallel Workers: 2
-> Sort
Locus: HashedWorkers
Parallel Workers: 2
Sort Key: c2
-> Parallel Seq Scan on t1
Locus: HashedWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(16 rows)
select * from t1 order by c2 asc limit 3 offset 5;
c1 | c2
----+----
6 | 7
7 | 8
8 | 9
(3 rows)
-- non-parallel results
set local enable_parallel = off;
explain(costs off, locus) select * from t1 order by c2 asc limit 3 offset 5;
QUERY PLAN
------------------------------------------------
Limit
Locus: Entry
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
Merge Key: c2
-> Limit
Locus: Hashed
-> Sort
Locus: Hashed
Sort Key: c2
-> Seq Scan on t1
Locus: Hashed
Optimizer: Postgres query optimizer
(13 rows)
select * from t1 order by c2 asc limit 3 offset 5;
c1 | c2
----+----
6 | 7
7 | 8
8 | 9
(3 rows)
abort;
--
-- Test one-phase Limit with parallel subpath
--
begin;
create table t1(c1 int, c2 int) with(parallel_workers=2);
insert into t1 select i, i+1 from generate_series(1, 100000) i;
analyze t1;
set local optimizer = off;
set local gp_enable_multiphase_limit = off;
set local enable_parallel = on;
explain(costs off, locus) select * from t1 order by c2 asc limit 3 offset 5;
QUERY PLAN
------------------------------------------------
Limit
Locus: Entry
-> Gather Motion 6:1 (slice1; segments: 6)
Locus: Entry
Merge Key: c2
-> Sort
Locus: HashedWorkers
Parallel Workers: 2
Sort Key: c2
-> Parallel Seq Scan on t1
Locus: HashedWorkers
Parallel Workers: 2
Optimizer: Postgres query optimizer
(13 rows)
select * from t1 order by c2 asc limit 3 offset 5;
c1 | c2
----+----
6 | 7
7 | 8
8 | 9
(3 rows)
-- non-parallel results
set local enable_parallel = off;
explain(costs off, locus) select * from t1 order by c2 asc limit 3 offset 5;
QUERY PLAN
------------------------------------------------
Limit
Locus: Entry
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
Merge Key: c2
-> Sort
Locus: Hashed
Sort Key: c2
-> Seq Scan on t1
Locus: Hashed
Optimizer: Postgres query optimizer
(11 rows)
select * from t1 order by c2 asc limit 3 offset 5;
c1 | c2
----+----
6 | 7
7 | 8
8 | 9
(3 rows)
abort;
--
-- Test Parallel Hash Left Anti Semi (Not-In) Join(parallel-oblivious).
--
create table t1(c1 int, c2 int) using ao_row distributed by (c1);
create table t2(c1 int, c2 int) using ao_row distributed by (c1);
create table t3_null(c1 int, c2 int) using ao_row distributed by (c1);
begin;
set local enable_parallel = on;
set local gp_appendonly_insert_files = 2;
set local gp_appendonly_insert_files_tuples_range = 100;
set local max_parallel_workers_per_gather = 2;
set local enable_parallel_hash = off;
insert into t1 select i, i from generate_series(1, 5000000) i;
insert into t2 select i+1, i from generate_series(1, 1200) i;
insert into t3_null select i+1, i from generate_series(1, 1200) i;
insert into t3_null values(NULL, NULL);
analyze t1;
analyze t2;
analyze t3_null;
explain(costs off) select sum(t1.c1) from t1 where c1 not in (select c1 from t2);
QUERY PLAN
---------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 6:1 (slice1; segments: 6)
-> Partial Aggregate
-> Hash Left Anti Semi (Not-In) Join
Hash Cond: (t1.c1 = t2.c1)
-> Parallel Seq Scan on t1
-> Hash
-> Broadcast Motion 3:6 (slice2; segments: 3)
-> Seq Scan on t2
Optimizer: Postgres query optimizer
(10 rows)
select sum(t1.c1) from t1 where c1 not in (select c1 from t2);
sum
----------------
12500001778200
(1 row)
explain(costs off) select * from t1 where c1 not in (select c1 from t3_null);
QUERY PLAN
---------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
-> Hash Left Anti Semi (Not-In) Join
Hash Cond: (t1.c1 = t3_null.c1)
-> Parallel Seq Scan on t1
-> Hash
-> Broadcast Motion 3:6 (slice2; segments: 3)
-> Seq Scan on t3_null
Optimizer: Postgres query optimizer
(8 rows)
select * from t1 where c1 not in (select c1 from t3_null);
c1 | c2
----+----
(0 rows)
-- non-parallel results.
set local enable_parallel = off;
select sum(t1.c1) from t1 where c1 not in (select c1 from t2);
sum
----------------
12500001778200
(1 row)
select * from t1 where c1 not in (select c1 from t3_null);
c1 | c2
----+----
(0 rows)
end;
drop table t1;
drop table t2;
drop table t3_null;
--
-- End of Test Parallel Hash Left Anti Semi (Not-In) Join.
--
--
-- Test Parallel-aware Hash Left Anti Semi (Not-In) Join.
--
begin;
create table t1(c1 int, c2 int) with(parallel_workers=2) distributed by (c1);
create table t2(c1 int, c2 int) with(parallel_workers=2) distributed by (c1);
create table t3_null(c1 int, c2 int) with(parallel_workers=2) distributed by (c1);
set local enable_parallel = on;
set local max_parallel_workers_per_gather = 2;
insert into t1 select i, i from generate_series(1, 500000) i;
insert into t2 select i, i+1 from generate_series(1, 500000) i;
insert into t3_null select i, i+1 from generate_series(1, 500000) i;
insert into t3_null values(NULL, NULL);
analyze t1;
analyze t2;
analyze t3_null;
explain(costs off) select sum(t1.c1) from t1 where c1 not in (select c2 from t2);
QUERY PLAN
------------------------------------------------------------------------------------
Finalize Aggregate
-> Gather Motion 6:1 (slice1; segments: 6)
-> Partial Aggregate
-> Parallel Hash Left Anti Semi (Not-In) Join
Hash Cond: (t1.c1 = t2.c2)
-> Parallel Seq Scan on t1
-> Parallel Hash
-> Broadcast Workers Motion 6:6 (slice2; segments: 6)
-> Parallel Seq Scan on t2
Optimizer: Postgres query optimizer
(10 rows)
select sum(t1.c1) from t1 where c1 not in (select c2 from t2);
sum
-----
1
(1 row)
explain(costs off) select * from t1 where c1 not in (select c2 from t3_null);
QUERY PLAN
------------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
-> Parallel Hash Left Anti Semi (Not-In) Join
Hash Cond: (t1.c1 = t3_null.c2)
-> Parallel Seq Scan on t1
-> Parallel Hash
-> Broadcast Workers Motion 6:6 (slice2; segments: 6)
-> Parallel Seq Scan on t3_null
Optimizer: Postgres query optimizer
(8 rows)
select * from t1 where c1 not in (select c2 from t3_null);
c1 | c2
----+----
(0 rows)
-- non-parallel results.
set local enable_parallel = off;
select sum(t1.c1) from t1 where c1 not in (select c2 from t2);
sum
-----
1
(1 row)
select * from t1 where c1 not in (select c2 from t3_null);
c1 | c2
----+----
(0 rows)
drop table t1;
drop table t2;
drop table t3_null;
end;
--
-- End of Test Parallel-aware Hash Left Anti Semi (Not-In) Join.
--
--
-- Test alter ao/aocs table parallel_workers options
--
begin;
set local optimizer = off;
set local enable_parallel = on;
-- ao table
create table ao (a INT, b INT) using ao_row;
insert into ao select i as a, i as b from generate_series(1, 100) AS i;
alter table ao set (parallel_workers = 2);
explain(costs off) select count(*) from ao;
QUERY PLAN
------------------------------------------------
Finalize Aggregate
-> Gather Motion 6:1 (slice1; segments: 6)
-> Partial Aggregate
-> Parallel Seq Scan on ao
Optimizer: Postgres query optimizer
(5 rows)
select count(*) from ao;
count
-------
100
(1 row)
alter table ao reset (parallel_workers);
-- aocs table
create table aocs (a INT, b INT) using ao_column;
insert into aocs select i as a, i as b from generate_series(1, 100) AS i;
alter table aocs set (parallel_workers = 2);
explain(costs off) select count(*) from aocs;
QUERY PLAN
------------------------------------------------
Finalize Aggregate
-> Gather Motion 6:1 (slice1; segments: 6)
-> Partial Aggregate
-> Parallel Seq Scan on aocs
Optimizer: Postgres query optimizer
(5 rows)
select count(*) from aocs;
count
-------
100
(1 row)
alter table aocs reset (parallel_workers);
abort;
--
-- Test locus after eliding mtion node.
--
begin;
create table t1(c1 int) distributed by (c1);
insert into t1 values(11), (12);
analyze t1;
explain(costs off, locus) select distinct min(c1), max(c1) from t1;
QUERY PLAN
------------------------------------------------
Aggregate
Locus: Entry
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Seq Scan on t1
Locus: Hashed
Optimizer: Postgres query optimizer
(7 rows)
abort;
begin;
create table t1(id int) distributed by (id);
create index on t1(id);
insert into t1 values(generate_series(1, 100));
analyze t1;
set enable_seqscan =off;
explain (locus, costs off)
select * from
(select count(id) from t1 where id > 10) ss
right join (values (1),(2),(3)) v(x) on true;
QUERY PLAN
---------------------------------------------------------------------
Nested Loop Left Join
Locus: Entry
-> Values Scan on "*VALUES*"
Locus: General
-> Materialize
Locus: Entry
-> Finalize Aggregate
Locus: Entry
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Partial Aggregate
Locus: Hashed
-> Index Only Scan using t1_id_idx on t1
Locus: Hashed
Index Cond: (id > 10)
Optimizer: Postgres query optimizer
(16 rows)
abort;
begin;
create table pagg_tab (a int, b int, c text, d int) partition by list(c);
create table pagg_tab_p1 partition of pagg_tab for values in ('0000', '0001', '0002', '0003', '0004');
create table pagg_tab_p2 partition of pagg_tab for values in ('0005', '0006', '0007', '0008');
create table pagg_tab_p3 partition of pagg_tab for values in ('0009', '0010', '0011');
insert into pagg_tab select i % 20, i % 30, to_char(i % 12, 'FM0000'), i % 30 from generate_series(0, 2999) i;
analyze pagg_tab;
set local enable_parallel to off;
set local enable_partitionwise_aggregate to true;
set local enable_partitionwise_join to true;
set local enable_incremental_sort to off;
set local enable_hashagg to false;
set local enable_parallel = off;
explain (costs off, locus)
select c, sum(a), avg(b), count(*) from pagg_tab group by 1 having avg(d) < 15 order by 1, 2, 3;
QUERY PLAN
------------------------------------------------------------------------
Sort
Locus: Entry
Sort Key: pagg_tab.c, (sum(pagg_tab.a)), (avg(pagg_tab.b))
-> Append
Locus: Entry
-> Finalize GroupAggregate
Locus: Entry
Group Key: pagg_tab.c
Filter: (avg(pagg_tab.d) < '15'::numeric)
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
Merge Key: pagg_tab.c
-> Partial GroupAggregate
Locus: Hashed
Group Key: pagg_tab.c
-> Sort
Locus: Hashed
Sort Key: pagg_tab.c
-> Seq Scan on pagg_tab_p1 pagg_tab
Locus: Hashed
-> Finalize GroupAggregate
Locus: Entry
Group Key: pagg_tab_1.c
Filter: (avg(pagg_tab_1.d) < '15'::numeric)
-> Gather Motion 3:1 (slice2; segments: 3)
Locus: Entry
Merge Key: pagg_tab_1.c
-> Partial GroupAggregate
Locus: Hashed
Group Key: pagg_tab_1.c
-> Sort
Locus: Hashed
Sort Key: pagg_tab_1.c
-> Seq Scan on pagg_tab_p2 pagg_tab_1
Locus: Hashed
-> Finalize GroupAggregate
Locus: Entry
Group Key: pagg_tab_2.c
Filter: (avg(pagg_tab_2.d) < '15'::numeric)
-> Gather Motion 3:1 (slice3; segments: 3)
Locus: Entry
Merge Key: pagg_tab_2.c
-> Partial GroupAggregate
Locus: Hashed
Group Key: pagg_tab_2.c
-> Sort
Locus: Hashed
Sort Key: pagg_tab_2.c
-> Seq Scan on pagg_tab_p3 pagg_tab_2
Locus: Hashed
Optimizer: Postgres query optimizer
(51 rows)
abort;
--
-- End of Test locus after eliding mtion node.
--
--
-- Test outer path has Motion of parallel plan.
--
begin;
create table t1(a int, b int) with(parallel_workers=3);
create table t2(b int, a int) with(parallel_workers=2);
insert into t1 select i, i+1 from generate_series(1, 10) i;
insert into t2 select i, i+1 from generate_series(1, 5) i;
analyze t1;
analyze t2;
set local optimizer=off;
set local enable_parallel=on;
set local enable_parallel_hash=off;
set local max_parallel_workers_per_gather= 4;
explain(costs off) select * from t1 right join t2 on t1.b = t2.a;
QUERY PLAN
------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
-> Hash Left Join
Hash Cond: (t2.a = t1.b)
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: t2.a
Hash Module: 3
-> Parallel Seq Scan on t2
-> Hash
-> Redistribute Motion 3:6 (slice3; segments: 3)
Hash Key: t1.b
Hash Module: 3
-> Seq Scan on t1
Optimizer: Postgres query optimizer
(13 rows)
abort;
--
-- Parallel Refresh AO Materialized View
--
create or replace function refresh_compare(ao_row bool, verbose bool, OUT parallel_is_better bool) as $$
declare
t timestamptz;
dur0 interval;
dur1 interval;
results0 RECORD;
results1 RECORD;
begin
create table t_p(c1 int, c2 int) with(parallel_workers=8) distributed by(c1);
insert into t_p select i, i+1 from generate_series(1, 10000000)i;
analyze t_p;
if ao_row then
create materialized view matv using ao_row as select sum(a.c2) as c2, avg(b.c1) as c1 from t_p a join t_p b on a.c1 = b.c1 with no data distributed by(c2);
else
create materialized view matv using ao_column as select sum(a.c2) as c2, avg(b.c1) as c1 from t_p a join t_p b on a.c1 = b.c1 with no data distributed by(c2);
end if;
-- refresh
set enable_parallel=off;
t = clock_timestamp();
refresh materialized view matv;
dur0 = age(clock_timestamp(), t);
select * into results0 from matv;
if refresh_compare.verbose then
raise notice 'Non-parallel refresh duration=%', dur0;
raise notice 'Non-parallel results=%', results0;
end if;
-- parallel refresh
set enable_parallel=on;
t = clock_timestamp();
refresh materialized view matv;
dur1 = age(clock_timestamp(), t);
select * into results1 from matv;
if refresh_compare.verbose then
raise notice 'Parallel refresh duration=%', dur1;
raise notice 'Parallel results=%', results1;
end if;
-- compare
if results0 <> results1 then
raise notice 'results of non-parallel % are not equal to parallel %', results0, results1;
end if;
parallel_is_better = dur0 > dur1;
if NOT parallel_is_better then
raise notice 'Non-parallel refresh duration=%', dur0;
raise notice 'Parallel refresh duration=%', dur1;
end if;
drop materialized view matv;
drop table t_p;
reset enable_parallel;
end
$$ language plpgsql;
begin;
set local max_parallel_workers_per_gather = 8;
-- start_ignore
-- FIXME: The test case is flaky, and the results are not always consistent.
select * from refresh_compare(true, false);
parallel_is_better
--------------------
t
(1 row)
select * from refresh_compare(false, false);
parallel_is_better
--------------------
t
(1 row)
-- end_ignore
drop function refresh_compare;
reset max_parallel_workers_per_gather;
end;
--
-- Parallel Create AO/AOCO Table AS
--
begin;
create table t_p2(c1 int, c2 int) with(parallel_workers=2) distributed by(c1);
insert into t_p2 select i, i+1 from generate_series(1, 10000000)i;
analyze t_p2;
set local enable_parallel = off;
explain(costs off) create table ctas_ao using ao_row as select sum(a.c2) as c2, avg(b.c1) as c1 from t_p2 a join t_p2 b on a.c1 = b.c1 distributed by(c2);
QUERY PLAN
--------------------------------------------------------
Redistribute Motion 1:3 (slice1; segments: 1)
Hash Key: (sum(a.c2))
-> Finalize Aggregate
-> Gather Motion 3:1 (slice2; segments: 3)
-> Partial Aggregate
-> Hash Join
Hash Cond: (a.c1 = b.c1)
-> Seq Scan on t_p2 a
-> Hash
-> Seq Scan on t_p2 b
Optimizer: Postgres query optimizer
(11 rows)
explain(costs off) create table ctas_aoco using ao_column as select sum(a.c2) as c2, avg(b.c1) as c1 from t_p2 a join t_p2 b on a.c1 = b.c1 distributed by(c2);
QUERY PLAN
--------------------------------------------------------
Redistribute Motion 1:3 (slice1; segments: 1)
Hash Key: (sum(a.c2))
-> Finalize Aggregate
-> Gather Motion 3:1 (slice2; segments: 3)
-> Partial Aggregate
-> Hash Join
Hash Cond: (a.c1 = b.c1)
-> Seq Scan on t_p2 a
-> Hash
-> Seq Scan on t_p2 b
Optimizer: Postgres query optimizer
(11 rows)
set local enable_parallel = on;
explain(costs off) create table ctas_ao using ao_row as select sum(a.c2) as c2, avg(b.c1) as c1 from t_p2 a join t_p2 b on a.c1 = b.c1 distributed by(c2);
QUERY PLAN
-----------------------------------------------------------------
Redistribute Motion 1:3 (slice1; segments: 1)
Hash Key: (sum(a.c2))
-> Finalize Aggregate
-> Gather Motion 6:1 (slice2; segments: 6)
-> Partial Aggregate
-> Parallel Hash Join
Hash Cond: (a.c1 = b.c1)
-> Parallel Seq Scan on t_p2 a
-> Parallel Hash
-> Parallel Seq Scan on t_p2 b
Optimizer: Postgres query optimizer
(11 rows)
explain(costs off) create table ctas_aoco using ao_column as select sum(a.c2) as c2, avg(b.c1) as c1 from t_p2 a join t_p2 b on a.c1 = b.c1 distributed by(c2);
QUERY PLAN
-----------------------------------------------------------------
Redistribute Motion 1:3 (slice1; segments: 1)
Hash Key: (sum(a.c2))
-> Finalize Aggregate
-> Gather Motion 6:1 (slice2; segments: 6)
-> Partial Aggregate
-> Parallel Hash Join
Hash Cond: (a.c1 = b.c1)
-> Parallel Seq Scan on t_p2 a
-> Parallel Hash
-> Parallel Seq Scan on t_p2 b
Optimizer: Postgres query optimizer
(11 rows)
abort;
--
-- Parallel Semi Join
--
begin;
set local optimizer=off;
set local enable_parallel=on;
set local force_parallel_mode =1 ;
set local min_parallel_table_scan_size = 0;
create table semi_t1 (c1 integer) with(parallel_workers=2) distributed randomly;
create table semi_t2 (c2 integer) with(parallel_workers=2) distributed randomly;
insert into semi_t1 values (generate_series (1,20000));
insert into semi_t2 values (generate_series (1,10000));
analyze semi_t1;
analyze semi_t2;
-- Parallel-aware Hash Semi Join
explain(costs off) select c1 from semi_t1 where not c1 >=all (select c2 from semi_t2 where c2 = c1);
QUERY PLAN
------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
-> Parallel Hash Semi Join
Hash Cond: (semi_t1.c1 = semi_t2.c2)
Join Filter: (semi_t1.c1 < semi_t2.c2)
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: semi_t1.c1
Hash Module: 3
-> Parallel Seq Scan on semi_t1
-> Parallel Hash
-> Redistribute Motion 6:6 (slice3; segments: 6)
Hash Key: semi_t2.c2
Hash Module: 3
-> Parallel Seq Scan on semi_t2
Optimizer: Postgres query optimizer
(14 rows)
-- Parallel-oblivious Hash Semi Join
set local enable_parallel_hash = off;
explain(costs off) select c1 from semi_t1 where not c1 >=all (select c2 from semi_t2 where c2 = c1);
QUERY PLAN
------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
-> Hash Semi Join
Hash Cond: (semi_t1.c1 = semi_t2.c2)
Join Filter: (semi_t1.c1 < semi_t2.c2)
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: semi_t1.c1
Hash Module: 3
-> Parallel Seq Scan on semi_t1
-> Hash
-> Redistribute Motion 3:6 (slice3; segments: 3)
Hash Key: semi_t2.c2
Hash Module: 3
-> Seq Scan on semi_t2
Optimizer: Postgres query optimizer
(14 rows)
-- Parallel Merge Semi Join
set local enable_hashjoin = off;
explain(costs off) select c1 from semi_t1 where not c1 >=all (select c2 from semi_t2 where c2 = c1);
QUERY PLAN
------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
-> Merge Semi Join
Merge Cond: (semi_t1.c1 = semi_t2.c2)
Join Filter: (semi_t1.c1 < semi_t2.c2)
-> Sort
Sort Key: semi_t1.c1
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: semi_t1.c1
Hash Module: 3
-> Parallel Seq Scan on semi_t1
-> Sort
Sort Key: semi_t2.c2
-> Redistribute Motion 3:6 (slice3; segments: 3)
Hash Key: semi_t2.c2
Hash Module: 3
-> Seq Scan on semi_t2
Optimizer: Postgres query optimizer
(17 rows)
set local enable_mergejoin = off;
set local enable_nestloop = on;
-- Parallel Nested Loop Semi Join
explain(costs off) select c1 from semi_t1 where not c1 >=all (select c2 from semi_t2 where c2 = c1);
QUERY PLAN
--------------------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
-> Nested Loop Semi Join
Join Filter: ((semi_t1.c1 < semi_t2.c2) AND (semi_t1.c1 = semi_t2.c2))
-> Redistribute Motion 6:6 (slice2; segments: 6)
Hash Key: semi_t1.c1
Hash Module: 3
-> Parallel Seq Scan on semi_t1
-> Materialize
-> Redistribute Motion 3:6 (slice3; segments: 3)
Hash Key: semi_t2.c2
Hash Module: 3
-> Seq Scan on semi_t2
Optimizer: Postgres query optimizer
(13 rows)
abort;
--
-- Test Materialize locus when enable_material is off.
--
begin;
create table t1(id int) distributed by (id);
create index on t1(id);
insert into t1 values(generate_series(1, 100));
analyze t1;
set enable_seqscan =off;
set enable_material =off;
explain (locus, costs off)
select * from
(select count(id) from t1 where id > 10) ss
right join (values (1),(2),(3)) v(x) on true;
QUERY PLAN
---------------------------------------------------------------------
Nested Loop Left Join
Locus: Entry
-> Values Scan on "*VALUES*"
Locus: General
-> Materialize
Locus: Entry
-> Finalize Aggregate
Locus: Entry
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Partial Aggregate
Locus: Hashed
-> Index Only Scan using t1_id_idx on t1
Locus: Hashed
Index Cond: (id > 10)
Optimizer: Postgres query optimizer
(16 rows)
abort;
-- Subplan locus, One-time flter locus is null
begin;
drop table if exists mrs_t1;
NOTICE: table "mrs_t1" does not exist, skipping
create table mrs_t1(x int) distributed by (x);
insert into mrs_t1 select generate_series(1,20);
analyze mrs_t1;
explain(locus, costs off) select * from mrs_t1 where exists (select x from mrs_t1 where x < -1);
QUERY PLAN
--------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
InitPlan 1 (returns $0) (slice2)
-> Gather Motion 3:1 (slice3; segments: 3)
Locus: Entry
-> Seq Scan on mrs_t1 mrs_t1_1
Locus: Hashed
Filter: (x < '-1'::integer)
-> Result
Locus: Hashed
One-Time Filter: $0
-> Seq Scan on mrs_t1
Locus: Hashed
Optimizer: Postgres query optimizer
(14 rows)
explain(locus, costs off) select * from mrs_t1 where exists (select x from mrs_t1 where x = 1);
QUERY PLAN
--------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
InitPlan 1 (returns $0) (slice2)
-> Gather Motion 1:1 (slice3; segments: 1)
Locus: Entry
-> Seq Scan on mrs_t1 mrs_t1_1
Locus: Hashed
Filter: (x = 1)
-> Result
Locus: Hashed
One-Time Filter: $0
-> Seq Scan on mrs_t1
Locus: Hashed
Optimizer: Postgres query optimizer
(14 rows)
explain(locus, costs off) select * from mrs_t1 where x in (select x-95 from mrs_t1) or x < 5;
QUERY PLAN
-----------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Seq Scan on mrs_t1
Locus: Hashed
Filter: ((hashed SubPlan 1) OR (x < 5))
SubPlan 1
-> Broadcast Motion 3:3 (slice2; segments: 3)
Locus: Replicated
-> Seq Scan on mrs_t1 mrs_t1_1
Locus: Hashed
Optimizer: Postgres query optimizer
(11 rows)
explain(locus, costs off) select * from pg_class where oid in (select x-95 from mrs_t1) or oid < 5;
QUERY PLAN
----------------------------------------------------
Seq Scan on pg_class
Locus: Entry
Filter: ((hashed SubPlan 1) OR (oid < '5'::oid))
SubPlan 1
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Seq Scan on mrs_t1
Locus: Hashed
Optimizer: Postgres query optimizer
(9 rows)
drop table if exists mrs_t1;
abort;
-- prepare, execute locus is null
begin;
create table t1(c1 int, c2 int);
analyze t1;
prepare t1_count(integer) as select count(*) from t1;
explain(locus, costs off) execute t1_count(1);
QUERY PLAN
------------------------------------------------
Aggregate
Locus: Entry
-> Gather Motion 3:1 (slice1; segments: 3)
Locus: Entry
-> Seq Scan on t1
Locus: Hashed
Optimizer: Postgres query optimizer
(7 rows)
abort;
-- Result locus is null
begin;
create table t1(id int) distributed by (id);
create index on t1(id);
insert into t1 values(generate_series(1, 10));
analyze t1;
explain(costs off, locus) select max(100) from t1;
QUERY PLAN
----------------------------------------------------------
Result
Locus: Entry
InitPlan 1 (returns $0) (slice1)
-> Limit
Locus: Entry
-> Gather Motion 3:1 (slice2; segments: 3)
Locus: Entry
-> Result
Locus: Hashed
One-Time Filter: (100 IS NOT NULL)
-> Seq Scan on t1
Locus: Hashed
Optimizer: Postgres query optimizer
(13 rows)
abort;
-- test Parallel Anti Join
begin;
create table t1_anti(a int, b int) with(parallel_workers=2) distributed by (a);
insert into t1_anti values(generate_series(1, 10));
create table t2_anti(a int, b int) with(parallel_workers=2) distributed by (b);
insert into t2_anti values(generate_series(5, 10));
explain(costs off, verbose)
select t1_anti.a, t1_anti.b from t1_anti left join t2_anti on t1_anti.a = t2_anti.a where t2_anti.a is null;
QUERY PLAN
------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Output: t1_anti.a, t1_anti.b
-> Hash Anti Join
Output: t1_anti.a, t1_anti.b
Hash Cond: (t1_anti.a = t2_anti.a)
-> Seq Scan on test_parallel.t1_anti
Output: t1_anti.a, t1_anti.b
-> Hash
Output: t2_anti.a
-> Redistribute Motion 3:3 (slice2; segments: 3)
Output: t2_anti.a
Hash Key: t2_anti.a
-> Seq Scan on test_parallel.t2_anti
Output: t2_anti.a
Settings: optimizer = 'off'
Optimizer: Postgres query optimizer
(16 rows)
select t1_anti.a, t1_anti.b from t1_anti left join t2_anti on t1_anti.a = t2_anti.a where t2_anti.a is null;
a | b
---+---
1 |
2 |
3 |
4 |
(4 rows)
set local enable_parallel = on;
set local min_parallel_table_scan_size = 0;
explain(costs off, verbose)
select t1_anti.a, t1_anti.b from t1_anti left join t2_anti on t1_anti.a = t2_anti.a where t2_anti.a is null;
QUERY PLAN
-----------------------------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Output: t1_anti.a, t1_anti.b
-> Parallel Hash Anti Join
Output: t1_anti.a, t1_anti.b
Hash Cond: (t1_anti.a = t2_anti.a)
-> Parallel Seq Scan on test_parallel.t1_anti
Output: t1_anti.a, t1_anti.b
-> Parallel Hash
Output: t2_anti.a
-> Redistribute Motion 6:6 (slice2; segments: 6)
Output: t2_anti.a
Hash Key: t2_anti.a
Hash Module: 3
-> Parallel Seq Scan on test_parallel.t2_anti
Output: t2_anti.a
Settings: enable_parallel = 'on', min_parallel_table_scan_size = '0', optimizer = 'off'
Optimizer: Postgres query optimizer
(17 rows)
select t1_anti.a, t1_anti.b from t1_anti left join t2_anti on t1_anti.a = t2_anti.a where t2_anti.a is null;
a | b
---+---
2 |
3 |
4 |
1 |
(4 rows)
set local enable_parallel_hash = off;
explain(costs off, verbose)
select t1_anti.a, t1_anti.b from t1_anti left join t2_anti on t1_anti.a = t2_anti.a where t2_anti.a is null;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------
Gather Motion 6:1 (slice1; segments: 6)
Output: t1_anti.a, t1_anti.b
-> Hash Anti Join
Output: t1_anti.a, t1_anti.b
Hash Cond: (t1_anti.a = t2_anti.a)
-> Redistribute Motion 6:6 (slice2; segments: 6)
Output: t1_anti.a, t1_anti.b
Hash Key: t1_anti.a
Hash Module: 3
-> Parallel Seq Scan on test_parallel.t1_anti
Output: t1_anti.a, t1_anti.b
-> Hash
Output: t2_anti.a
-> Redistribute Motion 3:6 (slice3; segments: 3)
Output: t2_anti.a
Hash Key: t2_anti.a
Hash Module: 3
-> Seq Scan on test_parallel.t2_anti
Output: t2_anti.a
Settings: enable_parallel = 'on', enable_parallel_hash = 'off', min_parallel_table_scan_size = '0', optimizer = 'off'
Optimizer: Postgres query optimizer
(21 rows)
select t1_anti.a, t1_anti.b from t1_anti left join t2_anti on t1_anti.a = t2_anti.a where t2_anti.a is null;
a | b
---+---
3 |
4 |
1 |
2 |
(4 rows)
abort;
-- start_ignore
drop schema test_parallel cascade;
-- end_ignore
reset gp_appendonly_insert_files;
reset force_parallel_mode;
reset optimizer;