From 07aa36fb45d34ac170df2048c1ad224813b7f659 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Wed, 16 Dec 2020 09:27:59 +0530 Subject: [PATCH v12 3/3] Tests For Parallel Inserts in CTAS --- src/test/regress/expected/write_parallel.out | 1226 ++++++++++++++++++ src/test/regress/sql/write_parallel.sql | 402 ++++++ 2 files changed, 1628 insertions(+) diff --git a/src/test/regress/expected/write_parallel.out b/src/test/regress/expected/write_parallel.out index 0c4da2591a..f8f1890228 100644 --- a/src/test/regress/expected/write_parallel.out +++ b/src/test/regress/expected/write_parallel.out @@ -76,4 +76,1230 @@ explain (costs off) create table parallel_write as execute prep_stmt; create table parallel_write as execute prep_stmt; drop table parallel_write; +-- +-- Test parallel inserts in create table as/select into/create materialized +-- view. +-- +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select length(stringu1) from tenk1; + QUERY PLAN +------------------------------------------------------------- + Gather (actual rows=0 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) +(5 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur as the table is temporary +explain (costs off, analyze on, timing off, summary off) +create temporary table parallel_write as select length(stringu1) from tenk1; + QUERY PLAN +------------------------------------------------------------- + Gather (actual rows=10000 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) +(4 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +create unlogged table parallel_write as select length(stringu1) from tenk1; + QUERY PLAN +------------------------------------------------------------- + Gather (actual rows=0 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) +(5 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +select length(stringu1) into parallel_write from tenk1; + QUERY PLAN +------------------------------------------------------------- + Gather (actual rows=0 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) +(5 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur as the table is temporary +explain (costs off, analyze on, timing off, summary off) +select length(stringu1) into temporary parallel_write from tenk1; + QUERY PLAN +------------------------------------------------------------- + Gather (actual rows=10000 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) +(4 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +select length(stringu1) into unlogged parallel_write from tenk1; + QUERY PLAN +------------------------------------------------------------- + Gather (actual rows=0 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) +(5 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur as the parallelism will not be picked +-- for select part because of for update clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select length(stringu1) from tenk1 for update; + QUERY PLAN +----------------------------------------------------- + LockRows (actual rows=10000 loops=1) + -> Seq Scan on tenk1 (actual rows=10000 loops=1) +(2 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +create materialized view parallel_mat_view as + select length(stringu1) from tenk1; + QUERY PLAN +------------------------------------------------------------- + Gather (actual rows=0 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Create parallel_mat_view + -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) +(5 rows) + +select count(*) from parallel_mat_view; + count +------- + 10000 +(1 row) + +drop materialized view parallel_mat_view; +-- parallel inserts must occur +prepare parallel_write_prep as select length(stringu1) from tenk1; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as execute parallel_write_prep; + QUERY PLAN +------------------------------------------------------------- + Gather (actual rows=0 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) +(5 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +deallocate parallel_write_prep; +drop table parallel_write; +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select now(), four from tenk1; + QUERY PLAN +------------------------------------------------------------- + Gather (actual rows=0 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=2000 loops=5) +(5 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur as the parallelism will not be picked +-- for select part because of the parallel unsafe function +create sequence parallel_write_sequence; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select nextval('parallel_write_sequence'), four from tenk1; + QUERY PLAN +----------------------------------------------- + Seq Scan on tenk1 (actual rows=10000 loops=1) +(1 row) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +drop sequence parallel_write_sequence; +-- parallel inserts must occur, as there is init plan that gets executed by +-- each parallel worker +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select two col1, + (select two from (select * from tenk2) as tt limit 1) col2 + from tenk1 where tenk1.four = 3; + QUERY PLAN +------------------------------------------------------------------------ + Gather (actual rows=0 loops=1) + Workers Planned: 4 + Params Evaluated: $1 + Workers Launched: 3 + -> Create parallel_write + InitPlan 1 (returns $1) + -> Limit (actual rows=1 loops=1) + -> Gather (actual rows=1 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Parallel Seq Scan on tenk2 (actual rows=1 loops=5) + -> Parallel Seq Scan on tenk1 (actual rows=625 loops=4) + Filter: (four = 3) + Rows Removed by Filter: 1875 +(14 rows) + +select count(*) from parallel_write; + count +------- + 2500 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur, as there is sub plan that gets executed by +-- the Gather node in leader +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select two col1, + (select tenk1.two from generate_series(1,1)) col2 + from tenk1 where tenk1.four = 3; + QUERY PLAN +--------------------------------------------------------------------- + Gather (actual rows=2500 loops=1) + Workers Planned: 4 + Workers Launched: 4 + -> Parallel Seq Scan on tenk1 (actual rows=500 loops=5) + Filter: (four = 3) + Rows Removed by Filter: 1500 + SubPlan 1 + -> Function Scan on generate_series (actual rows=1 loops=2500) +(8 rows) + +select count(*) from parallel_write; + count +------- + 2500 +(1 row) + +drop table parallel_write; +create table temp1(col1) as select * from generate_series(1,5); +create table temp2(col2) as select * from temp1; +create table temp3(col3) as select * from temp1; +-- parallel inserts must not occur, as there is a limit clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select * from temp1 limit 4; + QUERY PLAN +---------------------------------------------------------------- + Limit (actual rows=4 loops=1) + -> Gather (actual rows=4 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) +(5 rows) + +drop table parallel_write; +-- parallel inserts must not occur, as there is an order by clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select * from temp1 order by 1; + QUERY PLAN +---------------------------------------------------------------- + Gather Merge (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Sort (actual rows=1 loops=4) + Sort Key: col1 + Sort Method: quicksort Memory: 25kB + Worker 0: Sort Method: quicksort Memory: 25kB + Worker 1: Sort Method: quicksort Memory: 25kB + Worker 2: Sort Method: quicksort Memory: 25kB + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) +(10 rows) + +drop table parallel_write; +-- parallel inserts must not occur, as there is an order by clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select * from temp1 order by 1; + QUERY PLAN +---------------------------------------------------------------- + Gather Merge (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Sort (actual rows=1 loops=4) + Sort Key: col1 + Sort Method: quicksort Memory: 25kB + Worker 0: Sort Method: quicksort Memory: 25kB + Worker 1: Sort Method: quicksort Memory: 25kB + Worker 2: Sort Method: quicksort Memory: 25kB + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) +(10 rows) + +drop table parallel_write; +-- parallel inserts must not occur, as there is a distinct clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select distinct * from temp1; + QUERY PLAN +---------------------------------------------------------------- + HashAggregate (actual rows=5 loops=1) + Group Key: col1 + Batches: 1 Memory Usage: 40kB + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) +(7 rows) + +drop table parallel_write; +-- parallel inserts must not occur, as there is an aggregate and group clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select count(*) from temp1 group by col1; + QUERY PLAN +---------------------------------------------------------------------- + Finalize HashAggregate (actual rows=5 loops=1) + Group Key: col1 + Batches: 1 Memory Usage: 40kB + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Partial HashAggregate (actual rows=1 loops=4) + Group Key: col1 + Batches: 1 Memory Usage: 40kB + Worker 0: Batches: 1 Memory Usage: 40kB + Worker 1: Batches: 1 Memory Usage: 40kB + Worker 2: Batches: 1 Memory Usage: 40kB + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) +(13 rows) + +drop table parallel_write; +-- parallel inserts must not occur, as there is an aggregate, group and having +-- clauses +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select count(col1), (select col3 from + (select * from temp3) as tt limit 1) col4 from temp1, temp2 + where temp1.col1 = temp2.col2 group by col4 having count(col1) > 0; + QUERY PLAN +---------------------------------------------------------------------------------- + Finalize GroupAggregate (actual rows=1 loops=1) + Group Key: ($1) + Filter: (count(temp1.col1) > 0) + InitPlan 1 (returns $1) + -> Limit (actual rows=1 loops=1) + -> Gather (actual rows=1 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp3 (actual rows=0 loops=4) + -> Gather (actual rows=1 loops=1) + Workers Planned: 3 + Params Evaluated: $1 + Workers Launched: 3 + -> Partial GroupAggregate (actual rows=0 loops=4) + Group Key: $1 + -> Parallel Hash Join (actual rows=1 loops=4) + Hash Cond: (temp1.col1 = temp2.col2) + -> Parallel Seq Scan on temp1 (actual rows=5 loops=1) + -> Parallel Hash (actual rows=1 loops=4) + Buckets: 4096 Batches: 1 Memory Usage: 64kB + -> Parallel Seq Scan on temp2 (actual rows=5 loops=1) +(21 rows) + +drop table parallel_write; +-- parallel inserts must not occur, as there is a window function +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select avg(col1) OVER (PARTITION BY col1) from temp1; + QUERY PLAN +---------------------------------------------------------------------- + WindowAgg (actual rows=5 loops=1) + -> Sort (actual rows=5 loops=1) + Sort Key: col1 + Sort Method: quicksort Memory: 25kB + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) +(8 rows) + +drop table parallel_write; +-- nested loop join is the top node under which Gather node exists, so parallel +-- inserts must not occur +set enable_nestloop to on; +set enable_mergejoin to off; +set enable_hashjoin to off; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1, temp2 where temp1.col1 = temp2.col2; + QUERY PLAN +---------------------------------------------------------------------- + Nested Loop (actual rows=5 loops=1) + Join Filter: (temp1.col1 = temp2.col2) + Rows Removed by Join Filter: 20 + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) + -> Materialize (actual rows=5 loops=5) + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp2 (actual rows=1 loops=4) +(12 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +-- the top node is Gather under which merge join happens, so parallel inserts +-- must occur +set enable_nestloop to off; +set enable_mergejoin to on; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1, temp2 where temp1.col1 = temp2.col2; + QUERY PLAN +---------------------------------------------------------------------- + Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Merge Join (actual rows=1 loops=4) + Merge Cond: (temp1.col1 = temp2.col2) + -> Sort (actual rows=1 loops=4) + Sort Key: temp1.col1 + Sort Method: quicksort Memory: 25kB + Worker 0: Sort Method: quicksort Memory: 25kB + Worker 1: Sort Method: quicksort Memory: 25kB + Worker 2: Sort Method: quicksort Memory: 25kB + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) + -> Sort (actual rows=5 loops=1) + Sort Key: temp2.col2 + Sort Method: quicksort Memory: 25kB + -> Seq Scan on temp2 (actual rows=5 loops=1) +(17 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +-- parallel hash join happens under Gather node, so parallel inserts must occur +set enable_mergejoin to off; +set enable_hashjoin to on; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1, temp2 where temp1.col1 = temp2.col2; + QUERY PLAN +---------------------------------------------------------------------- + Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Hash Join (actual rows=1 loops=4) + Hash Cond: (temp1.col1 = temp2.col2) + -> Parallel Seq Scan on temp1 (actual rows=5 loops=1) + -> Parallel Hash (actual rows=1 loops=4) + Buckets: 4096 Batches: 1 Memory Usage: 64kB + -> Parallel Seq Scan on temp2 (actual rows=5 loops=1) +(10 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +reset enable_nestloop; +reset enable_mergejoin; +reset enable_hashjoin; +-- test cases for performing parallel inserts when Append node is at the top +-- and Gather node is in one of its direct sub plans. +-- case 1: parallel inserts must occur at each Gather node as we can push the +-- CTAS dest receiver. +-- Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Gather +-- ->Parallel Seq Scan +-- ->Gather +-- ->Parallel Seq Scan +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 where col1 = 5 union all + select * from temp2 where col2 = 5 union all + select * from temp2 where col2 = 5; + QUERY PLAN +---------------------------------------------------------------------- + Append (actual rows=0 loops=1) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Seq Scan on temp1 (actual rows=0 loops=4) + Filter: (col1 = 5) + Rows Removed by Filter: 1 + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Seq Scan on temp2 (actual rows=0 loops=4) + Filter: (col2 = 5) + Rows Removed by Filter: 1 + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Seq Scan on temp2 temp2_1 (actual rows=0 loops=4) + Filter: (col2 = 5) + Rows Removed by Filter: 1 +(22 rows) + +select count(*) from parallel_write; + count +------- + 3 +(1 row) + +drop table parallel_write; +-- case 2: parallel inserts must occur at the top Gather node as we can push +-- the CTAS dest receiver to it. +-- Gather +-- ->Parallel Append +-- ->Parallel Seq Scan +-- ->Parallel Seq Scan +-- ->Parallel Seq Scan +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 union all + select * from temp2 union all + select * from temp2; + QUERY PLAN +------------------------------------------------------------------------ + Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Append (actual rows=4 loops=4) + -> Parallel Seq Scan on temp1 (actual rows=5 loops=1) + -> Parallel Seq Scan on temp2 (actual rows=5 loops=1) + -> Parallel Seq Scan on temp2 temp2_1 (actual rows=5 loops=1) +(8 rows) + +select count(*) from parallel_write; + count +------- + 15 +(1 row) + +drop table parallel_write; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select (select col2 from temp2 limit 1) col2 from temp1 union all + select (select col2 from temp2 limit 1) col2 from temp1 union all + select * from temp2; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $1, $3 + Workers Launched: 1 + -> Create parallel_write + InitPlan 1 (returns $1) + -> Limit (actual rows=1 loops=1) + -> Gather (actual rows=1 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp2 temp2_1 (actual rows=0 loops=4) + InitPlan 2 (returns $3) + -> Limit (actual rows=1 loops=1) + -> Gather (actual rows=1 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp2 temp2_2 (actual rows=0 loops=4) + -> Parallel Append (actual rows=8 loops=2) + -> Parallel Seq Scan on temp1 (actual rows=5 loops=1) + -> Parallel Seq Scan on temp1 temp1_1 (actual rows=5 loops=1) + -> Parallel Seq Scan on temp2 (actual rows=5 loops=1) +(21 rows) + +select count(*) from parallel_write; + count +------- + 15 +(1 row) + +drop table parallel_write; +-- case 3: parallel inserts must occur at each Gather node as we can push the +-- CTAS dest receiver. Non-Gather nodes will do inserts by sending tuples to +-- Append and from there to CTAS dest receiver. +-- Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Seq Scan / Join / any other non-Gather node +-- ->Gather +-- ->Parallel Seq Scan +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 where col1 = 5 union all + select (select temp1.col1 from temp2 limit 1) col2 from temp1 union all + select * from temp1 where col1 = 5; + QUERY PLAN +------------------------------------------------------------------------------- + Append (actual rows=5 loops=1) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Seq Scan on temp1 temp1_1 (actual rows=0 loops=4) + Filter: (col1 = 5) + Rows Removed by Filter: 1 + -> Seq Scan on temp1 (actual rows=5 loops=1) + SubPlan 1 + -> Limit (actual rows=1 loops=5) + -> Gather (actual rows=1 loops=5) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp2 (actual rows=0 loops=20) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Seq Scan on temp1 temp1_2 (actual rows=0 loops=4) + Filter: (col1 = 5) + Rows Removed by Filter: 1 +(22 rows) + +select count(*) from parallel_write; + count +------- + 7 +(1 row) + +drop table parallel_write; +alter table temp2 set (parallel_workers = 0); +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select * from temp1 where col1 = (select 1) union all select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2); + QUERY PLAN +------------------------------------------------------------------------ + Append (actual rows=1 loops=1) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $0 + Workers Launched: 3 + -> Create parallel_write + InitPlan 1 (returns $0) + -> Result (actual rows=1 loops=1) + -> Parallel Seq Scan on temp1 (actual rows=0 loops=4) + Filter: (col1 = $0) + Rows Removed by Filter: 1 + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $1 + Workers Launched: 3 + -> Create parallel_write + InitPlan 2 (returns $1) + -> Result (actual rows=1 loops=1) + -> Parallel Seq Scan on temp1 temp1_1 (actual rows=0 loops=4) + Filter: (col1 = $1) + Rows Removed by Filter: 1 + -> Seq Scan on temp2 (actual rows=1 loops=1) + Filter: (col2 = $2) + Rows Removed by Filter: 4 + InitPlan 3 (returns $2) + -> Result (actual rows=1 loops=1) +(26 rows) + +select count(*) from parallel_write; + count +------- + 3 +(1 row) + +alter table temp2 reset (parallel_workers); +drop table parallel_write; +-- case 4: parallel inserts must not occur as there will be no direct Gather +-- node under Append node. Non-Gather nodes will do inserts by sending tuples +-- to Append and from there to CTAS dest receiver. +-- Append +-- ->Seq Scan / Join / any other non-Gather node +-- ->Seq Scan / Join / any other non-Gather node +-- ->Seq Scan / Join / any other non-Gather node +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 union all + select * from temp2 union all + select (select temp1.col1 from temp2 limit 1) col2 from temp1; + QUERY PLAN +--------------------------------------------------------------------------------------- + Append (actual rows=15 loops=1) + -> Seq Scan on temp1 (actual rows=5 loops=1) + -> Seq Scan on temp2 (actual rows=5 loops=1) + -> Seq Scan on temp1 temp1_1 (actual rows=5 loops=1) + SubPlan 1 + -> Limit (actual rows=1 loops=5) + -> Gather (actual rows=1 loops=5) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp2 temp2_1 (actual rows=0 loops=20) +(10 rows) + +select count(*) from parallel_write; + count +------- + 15 +(1 row) + +drop table parallel_write; +-- case 5: parallel inserts must occur at the top Gather node as we can push +-- the CTAS dest receiver to it. +-- Gather +-- ->Parallel Append +-- ->Seq Scan / Join / any other non-Gather node +-- ->Parallel Seq Scan +-- ->Parallel Seq Scan +alter table temp2 set (parallel_workers = 0); +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 union all + select * from temp2 union all + select * from temp1; + QUERY PLAN +------------------------------------------------------------------------ + Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Append (actual rows=4 loops=4) + -> Seq Scan on temp2 (actual rows=5 loops=1) + -> Parallel Seq Scan on temp1 (actual rows=5 loops=1) + -> Parallel Seq Scan on temp1 temp1_1 (actual rows=5 loops=1) +(8 rows) + +select count(*) from parallel_write; + count +------- + 15 +(1 row) + +drop table parallel_write; +alter table temp2 reset (parallel_workers); +-- case 6: parallel inserts must occur at each Gather node as we can push the +-- CTAS dest receiver. +-- Append +-- ->Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Gather +-- ->Gather +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from temp2 where col2 = (select 2) union all + select * from temp2 where col2 = (select 2); + QUERY PLAN +---------------------------------------------------------------------------- + Append (actual rows=0 loops=1) + -> Append (actual rows=0 loops=1) + InitPlan 1 (returns $0) + -> Result (actual rows=1 loops=1) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $0, $1 + Workers Launched: 3 + -> Create parallel_write + InitPlan 2 (returns $1) + -> Result (actual rows=1 loops=1) + -> Result (actual rows=0 loops=4) + One-Time Filter: ($1 = $0) + -> Parallel Seq Scan on temp1 (actual rows=0 loops=4) + Filter: (col1 = $0) + Rows Removed by Filter: 1 + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $0, $2 + Workers Launched: 3 + -> Create parallel_write + InitPlan 3 (returns $2) + -> Result (actual rows=1 loops=1) + -> Result (actual rows=0 loops=4) + One-Time Filter: ($2 = $0) + -> Parallel Seq Scan on temp2 (never executed) + Filter: (col2 = $0) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $3 + Workers Launched: 3 + -> Create parallel_write + InitPlan 4 (returns $3) + -> Result (actual rows=1 loops=1) + -> Parallel Seq Scan on temp2 temp2_1 (actual rows=0 loops=4) + Filter: (col2 = $3) + Rows Removed by Filter: 1 + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $4 + Workers Launched: 3 + -> Create parallel_write + InitPlan 5 (returns $4) + -> Result (actual rows=1 loops=1) + -> Parallel Seq Scan on temp2 temp2_2 (actual rows=0 loops=4) + Filter: (col2 = $4) + Rows Removed by Filter: 1 +(47 rows) + +select count(*) from parallel_write; + count +------- + 3 +(1 row) + +drop table parallel_write; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from temp1 where col1 = 5 union all + select * from temp2 where col2 = 5; + QUERY PLAN +------------------------------------------------------------------------------------ + Append (actual rows=0 loops=1) + -> Append (actual rows=0 loops=1) + InitPlan 1 (returns $0) + -> Result (actual rows=1 loops=1) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $0, $1 + Workers Launched: 3 + -> Create parallel_write + InitPlan 2 (returns $1) + -> Result (actual rows=1 loops=1) + -> Result (actual rows=0 loops=4) + One-Time Filter: ($1 = $0) + -> Parallel Seq Scan on temp1 (actual rows=0 loops=4) + Filter: (col1 = $0) + Rows Removed by Filter: 1 + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $0, $2 + Workers Launched: 3 + -> Create parallel_write + InitPlan 3 (returns $2) + -> Result (actual rows=1 loops=1) + -> Result (actual rows=0 loops=4) + One-Time Filter: ($2 = $0) + -> Parallel Seq Scan on temp2 (never executed) + Filter: (col2 = $0) + -> Append (actual rows=0 loops=1) + InitPlan 4 (returns $3) + -> Result (actual rows=1 loops=1) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $3, $4 + Workers Launched: 3 + -> Create parallel_write + InitPlan 5 (returns $4) + -> Result (actual rows=1 loops=1) + -> Result (actual rows=0 loops=4) + One-Time Filter: ($4 = $3) + -> Parallel Seq Scan on temp1 temp1_1 (actual rows=0 loops=4) + Filter: (col1 = $3) + Rows Removed by Filter: 1 + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $3, $5 + Workers Launched: 3 + -> Create parallel_write + InitPlan 6 (returns $5) + -> Result (actual rows=1 loops=1) + -> Result (actual rows=0 loops=4) + One-Time Filter: ($5 = $3) + -> Parallel Seq Scan on temp2 temp2_1 (never executed) + Filter: (col2 = $3) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Seq Scan on temp1 temp1_2 (actual rows=0 loops=4) + Filter: (col1 = 5) + Rows Removed by Filter: 1 + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Seq Scan on temp2 temp2_2 (actual rows=0 loops=4) + Filter: (col2 = 5) + Rows Removed by Filter: 1 +(67 rows) + +select count(*) from parallel_write; + count +------- + 4 +(1 row) + +drop table parallel_write; +-- case 7: parallel inserts must occur at each Gather node as we can push the +-- CTAS dest receiver. Non-Gather nodes will do inserts by sending tuples +-- to Append and from there to CTAS dest receiver. +-- Append +-- ->Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Seq Scan / Join / any other non-Gather node +-- ->Gather +alter table temp2 set (parallel_workers = 0); +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from temp2 where col2 = (select 2) union all + select * from temp1 where col1 = (select 2); + QUERY PLAN +---------------------------------------------------------------------------- + Append (actual rows=1 loops=1) + -> Append (actual rows=0 loops=1) + InitPlan 1 (returns $0) + -> Result (actual rows=1 loops=1) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $0, $1 + Workers Launched: 3 + -> Create parallel_write + InitPlan 2 (returns $1) + -> Result (actual rows=1 loops=1) + -> Result (actual rows=0 loops=4) + One-Time Filter: ($1 = $0) + -> Parallel Seq Scan on temp1 (actual rows=0 loops=4) + Filter: (col1 = $0) + Rows Removed by Filter: 1 + -> Result (actual rows=0 loops=1) + One-Time Filter: ($2 = $0) + InitPlan 3 (returns $2) + -> Result (actual rows=1 loops=1) + -> Seq Scan on temp2 (never executed) + Filter: (col2 = $0) + -> Seq Scan on temp2 temp2_1 (actual rows=1 loops=1) + Filter: (col2 = $3) + Rows Removed by Filter: 4 + InitPlan 4 (returns $3) + -> Result (actual rows=1 loops=1) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $4 + Workers Launched: 3 + -> Create parallel_write + InitPlan 5 (returns $4) + -> Result (actual rows=1 loops=1) + -> Parallel Seq Scan on temp1 temp1_1 (actual rows=0 loops=4) + Filter: (col1 = $4) + Rows Removed by Filter: 1 +(37 rows) + +select count(*) from parallel_write; + count +------- + 3 +(1 row) + +drop table parallel_write; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from temp1 where col1 = 5 union all + select * from temp2 where col2 = 5; + QUERY PLAN +------------------------------------------------------------------------------------ + Append (actual rows=1 loops=1) + -> Append (actual rows=0 loops=1) + InitPlan 1 (returns $0) + -> Result (actual rows=1 loops=1) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $0, $1 + Workers Launched: 3 + -> Create parallel_write + InitPlan 2 (returns $1) + -> Result (actual rows=1 loops=1) + -> Result (actual rows=0 loops=4) + One-Time Filter: ($1 = $0) + -> Parallel Seq Scan on temp1 (actual rows=0 loops=4) + Filter: (col1 = $0) + Rows Removed by Filter: 1 + -> Result (actual rows=0 loops=1) + One-Time Filter: ($2 = $0) + InitPlan 3 (returns $2) + -> Result (actual rows=1 loops=1) + -> Seq Scan on temp2 (never executed) + Filter: (col2 = $0) + -> Append (actual rows=0 loops=1) + InitPlan 4 (returns $3) + -> Result (actual rows=1 loops=1) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Params Evaluated: $3, $4 + Workers Launched: 3 + -> Create parallel_write + InitPlan 5 (returns $4) + -> Result (actual rows=1 loops=1) + -> Result (actual rows=0 loops=4) + One-Time Filter: ($4 = $3) + -> Parallel Seq Scan on temp1 temp1_1 (actual rows=0 loops=4) + Filter: (col1 = $3) + Rows Removed by Filter: 1 + -> Result (actual rows=0 loops=1) + One-Time Filter: ($5 = $3) + InitPlan 6 (returns $5) + -> Result (actual rows=1 loops=1) + -> Seq Scan on temp2 temp2_1 (never executed) + Filter: (col2 = $3) + -> Gather (actual rows=0 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Create parallel_write + -> Parallel Seq Scan on temp1 temp1_2 (actual rows=0 loops=4) + Filter: (col1 = 5) + Rows Removed by Filter: 1 + -> Seq Scan on temp2 temp2_2 (actual rows=1 loops=1) + Filter: (col2 = 5) + Rows Removed by Filter: 4 +(53 rows) + +select count(*) from parallel_write; + count +------- + 4 +(1 row) + +drop table parallel_write; +alter table temp2 reset (parallel_workers); +-- case 8: parallel inserts must not occur because there is no Gather or Append +-- node at the top for union, except/except all, intersect/intersect all +-- cases. +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 union + select * from temp2; + QUERY PLAN +---------------------------------------------------------------------- + HashAggregate (actual rows=5 loops=1) + Group Key: temp1.col1 + Batches: 1 Memory Usage: 217kB + -> Append (actual rows=10 loops=1) + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp2 (actual rows=1 loops=4) +(12 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 except + select * from temp2 where col2 < 3; + QUERY PLAN +---------------------------------------------------------------------------- + HashSetOp Except (actual rows=3 loops=1) + -> Append (actual rows=7 loops=1) + -> Subquery Scan on "*SELECT* 1" (actual rows=5 loops=1) + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) + -> Subquery Scan on "*SELECT* 2" (actual rows=2 loops=1) + -> Gather (actual rows=2 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp2 (actual rows=0 loops=4) + Filter: (col2 < 3) + Rows Removed by Filter: 1 +(14 rows) + +select count(*) from parallel_write; + count +------- + 3 +(1 row) + +drop table parallel_write; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 except all + select * from temp2 where col2 < 3; + QUERY PLAN +---------------------------------------------------------------------------- + HashSetOp Except All (actual rows=3 loops=1) + -> Append (actual rows=7 loops=1) + -> Subquery Scan on "*SELECT* 1" (actual rows=5 loops=1) + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) + -> Subquery Scan on "*SELECT* 2" (actual rows=2 loops=1) + -> Gather (actual rows=2 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp2 (actual rows=0 loops=4) + Filter: (col2 < 3) + Rows Removed by Filter: 1 +(14 rows) + +select count(*) from parallel_write; + count +------- + 3 +(1 row) + +drop table parallel_write; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 intersect + select * from temp2; + QUERY PLAN +---------------------------------------------------------------------------- + HashSetOp Intersect (actual rows=5 loops=1) + -> Append (actual rows=10 loops=1) + -> Subquery Scan on "*SELECT* 1" (actual rows=5 loops=1) + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) + -> Subquery Scan on "*SELECT* 2" (actual rows=5 loops=1) + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp2 (actual rows=1 loops=4) +(12 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 intersect all + select * from temp2; + QUERY PLAN +---------------------------------------------------------------------------- + HashSetOp Intersect All (actual rows=5 loops=1) + -> Append (actual rows=10 loops=1) + -> Subquery Scan on "*SELECT* 1" (actual rows=5 loops=1) + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp1 (actual rows=1 loops=4) + -> Subquery Scan on "*SELECT* 2" (actual rows=5 loops=1) + -> Gather (actual rows=5 loops=1) + Workers Planned: 3 + Workers Launched: 3 + -> Parallel Seq Scan on temp2 (actual rows=1 loops=4) +(12 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +drop table temp1; +drop table temp2; +drop table temp3; rollback; diff --git a/src/test/regress/sql/write_parallel.sql b/src/test/regress/sql/write_parallel.sql index 78b479cedf..67de31fb91 100644 --- a/src/test/regress/sql/write_parallel.sql +++ b/src/test/regress/sql/write_parallel.sql @@ -39,4 +39,406 @@ explain (costs off) create table parallel_write as execute prep_stmt; create table parallel_write as execute prep_stmt; drop table parallel_write; +-- +-- Test parallel inserts in create table as/select into/create materialized +-- view. +-- + +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select length(stringu1) from tenk1; +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur as the table is temporary +explain (costs off, analyze on, timing off, summary off) +create temporary table parallel_write as select length(stringu1) from tenk1; +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +create unlogged table parallel_write as select length(stringu1) from tenk1; +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +select length(stringu1) into parallel_write from tenk1; +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur as the table is temporary +explain (costs off, analyze on, timing off, summary off) +select length(stringu1) into temporary parallel_write from tenk1; +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +select length(stringu1) into unlogged parallel_write from tenk1; +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur as the parallelism will not be picked +-- for select part because of for update clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select length(stringu1) from tenk1 for update; +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +create materialized view parallel_mat_view as + select length(stringu1) from tenk1; +select count(*) from parallel_mat_view; +drop materialized view parallel_mat_view; + +-- parallel inserts must occur +prepare parallel_write_prep as select length(stringu1) from tenk1; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as execute parallel_write_prep; +select count(*) from parallel_write; +deallocate parallel_write_prep; +drop table parallel_write; + +-- parallel inserts must occur +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select now(), four from tenk1; +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur as the parallelism will not be picked +-- for select part because of the parallel unsafe function +create sequence parallel_write_sequence; +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select nextval('parallel_write_sequence'), four from tenk1; +select count(*) from parallel_write; +drop table parallel_write; +drop sequence parallel_write_sequence; + +-- parallel inserts must occur, as there is init plan that gets executed by +-- each parallel worker +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select two col1, + (select two from (select * from tenk2) as tt limit 1) col2 + from tenk1 where tenk1.four = 3; +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur, as there is sub plan that gets executed by +-- the Gather node in leader +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select two col1, + (select tenk1.two from generate_series(1,1)) col2 + from tenk1 where tenk1.four = 3; +select count(*) from parallel_write; +drop table parallel_write; + +create table temp1(col1) as select * from generate_series(1,5); +create table temp2(col2) as select * from temp1; +create table temp3(col3) as select * from temp1; + +-- parallel inserts must not occur, as there is a limit clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select * from temp1 limit 4; +drop table parallel_write; + +-- parallel inserts must not occur, as there is an order by clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select * from temp1 order by 1; +drop table parallel_write; + +-- parallel inserts must not occur, as there is an order by clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select * from temp1 order by 1; +drop table parallel_write; + +-- parallel inserts must not occur, as there is a distinct clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select distinct * from temp1; +drop table parallel_write; + +-- parallel inserts must not occur, as there is an aggregate and group clause +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select count(*) from temp1 group by col1; +drop table parallel_write; + +-- parallel inserts must not occur, as there is an aggregate, group and having +-- clauses +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select count(col1), (select col3 from + (select * from temp3) as tt limit 1) col4 from temp1, temp2 + where temp1.col1 = temp2.col2 group by col4 having count(col1) > 0; +drop table parallel_write; + +-- parallel inserts must not occur, as there is a window function +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select avg(col1) OVER (PARTITION BY col1) from temp1; +drop table parallel_write; + +-- nested loop join is the top node under which Gather node exists, so parallel +-- inserts must not occur +set enable_nestloop to on; +set enable_mergejoin to off; +set enable_hashjoin to off; + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1, temp2 where temp1.col1 = temp2.col2; +select count(*) from parallel_write; +drop table parallel_write; + +-- the top node is Gather under which merge join happens, so parallel inserts +-- must occur +set enable_nestloop to off; +set enable_mergejoin to on; + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1, temp2 where temp1.col1 = temp2.col2; +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel hash join happens under Gather node, so parallel inserts must occur +set enable_mergejoin to off; +set enable_hashjoin to on; + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1, temp2 where temp1.col1 = temp2.col2; +select count(*) from parallel_write; +drop table parallel_write; + +reset enable_nestloop; +reset enable_mergejoin; +reset enable_hashjoin; + +-- test cases for performing parallel inserts when Append node is at the top +-- and Gather node is in one of its direct sub plans. + +-- case 1: parallel inserts must occur at each Gather node as we can push the +-- CTAS dest receiver. +-- Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Gather +-- ->Parallel Seq Scan +-- ->Gather +-- ->Parallel Seq Scan + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 where col1 = 5 union all + select * from temp2 where col2 = 5 union all + select * from temp2 where col2 = 5; +select count(*) from parallel_write; +drop table parallel_write; + +-- case 2: parallel inserts must occur at the top Gather node as we can push +-- the CTAS dest receiver to it. +-- Gather +-- ->Parallel Append +-- ->Parallel Seq Scan +-- ->Parallel Seq Scan +-- ->Parallel Seq Scan + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 union all + select * from temp2 union all + select * from temp2; +select count(*) from parallel_write; +drop table parallel_write; + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select (select col2 from temp2 limit 1) col2 from temp1 union all + select (select col2 from temp2 limit 1) col2 from temp1 union all + select * from temp2; +select count(*) from parallel_write; +drop table parallel_write; + +-- case 3: parallel inserts must occur at each Gather node as we can push the +-- CTAS dest receiver. Non-Gather nodes will do inserts by sending tuples to +-- Append and from there to CTAS dest receiver. +-- Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Seq Scan / Join / any other non-Gather node +-- ->Gather +-- ->Parallel Seq Scan + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 where col1 = 5 union all + select (select temp1.col1 from temp2 limit 1) col2 from temp1 union all + select * from temp1 where col1 = 5; +select count(*) from parallel_write; +drop table parallel_write; + +alter table temp2 set (parallel_workers = 0); +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as select * from temp1 where col1 = (select 1) union all select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2); +select count(*) from parallel_write; +alter table temp2 reset (parallel_workers); +drop table parallel_write; + +-- case 4: parallel inserts must not occur as there will be no direct Gather +-- node under Append node. Non-Gather nodes will do inserts by sending tuples +-- to Append and from there to CTAS dest receiver. +-- Append +-- ->Seq Scan / Join / any other non-Gather node +-- ->Seq Scan / Join / any other non-Gather node +-- ->Seq Scan / Join / any other non-Gather node + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 union all + select * from temp2 union all + select (select temp1.col1 from temp2 limit 1) col2 from temp1; +select count(*) from parallel_write; +drop table parallel_write; + +-- case 5: parallel inserts must occur at the top Gather node as we can push +-- the CTAS dest receiver to it. +-- Gather +-- ->Parallel Append +-- ->Seq Scan / Join / any other non-Gather node +-- ->Parallel Seq Scan +-- ->Parallel Seq Scan + +alter table temp2 set (parallel_workers = 0); + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 union all + select * from temp2 union all + select * from temp1; +select count(*) from parallel_write; +drop table parallel_write; + +alter table temp2 reset (parallel_workers); + +-- case 6: parallel inserts must occur at each Gather node as we can push the +-- CTAS dest receiver. +-- Append +-- ->Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Gather +-- ->Gather + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from temp2 where col2 = (select 2) union all + select * from temp2 where col2 = (select 2); +select count(*) from parallel_write; +drop table parallel_write; + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from temp1 where col1 = 5 union all + select * from temp2 where col2 = 5; +select count(*) from parallel_write; +drop table parallel_write; + +-- case 7: parallel inserts must occur at each Gather node as we can push the +-- CTAS dest receiver. Non-Gather nodes will do inserts by sending tuples +-- to Append and from there to CTAS dest receiver. +-- Append +-- ->Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Append +-- ->Gather +-- ->Parallel Seq Scan +-- ->Seq Scan / Join / any other non-Gather node +-- ->Gather + +alter table temp2 set (parallel_workers = 0); + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from temp2 where col2 = (select 2) union all + select * from temp1 where col1 = (select 2); +select count(*) from parallel_write; +drop table parallel_write; + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from (select * from temp1 where col1 = (select 1) union all + select * from temp2 where col2 = (select 2)) as tt + where col1 = (select 1) union all + select * from temp1 where col1 = 5 union all + select * from temp2 where col2 = 5; +select count(*) from parallel_write; +drop table parallel_write; + +alter table temp2 reset (parallel_workers); + +-- case 8: parallel inserts must not occur because there is no Gather or Append +-- node at the top for union, except/except all, intersect/intersect all +-- cases. + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 union + select * from temp2; +select count(*) from parallel_write; +drop table parallel_write; + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 except + select * from temp2 where col2 < 3; +select count(*) from parallel_write; +drop table parallel_write; + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 except all + select * from temp2 where col2 < 3; +select count(*) from parallel_write; +drop table parallel_write; + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 intersect + select * from temp2; +select count(*) from parallel_write; +drop table parallel_write; + +explain (costs off, analyze on, timing off, summary off) +create table parallel_write as + select * from temp1 intersect all + select * from temp2; +select count(*) from parallel_write; +drop table parallel_write; + +drop table temp1; +drop table temp2; +drop table temp3; rollback; -- 2.25.1