From 61641393e4c1d90a47f2a070d6e9e020e6f014e4 Mon Sep 17 00:00:00 2001 From: Bharath Rupireddy Date: Mon, 28 Dec 2020 16:49:43 +0530 Subject: [PATCH v20 3/4] Tests And Docs For Parallel Inserts in CTAS --- doc/src/sgml/ref/create_table_as.sgml | 31 +- src/test/regress/expected/write_parallel.out | 559 +++++++++++++++++++ src/test/regress/sql/write_parallel.sql | 211 +++++++ 3 files changed, 796 insertions(+), 5 deletions(-) diff --git a/doc/src/sgml/ref/create_table_as.sgml b/doc/src/sgml/ref/create_table_as.sgml index 07558ab56c..35903701ed 100644 --- a/doc/src/sgml/ref/create_table_as.sgml +++ b/doc/src/sgml/ref/create_table_as.sgml @@ -37,11 +37,13 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI CREATE TABLE AS creates a table and fills it - with data computed by a SELECT command. - The table columns have the - names and data types associated with the output columns of the - SELECT (except that you can override the column - names by giving an explicit list of new column names). + with data computed by a SELECT command. When the + node at the top of the SELECT plan is + Gather and there are no projections to be performed + by it, then the created table can be filled by the workers in parallel. + The table columns have the names and data types associated with the output + columns of the SELECT (except that you can override the + column names by giving an explicit list of new column names). @@ -297,6 +299,25 @@ PREPARE recentfilms(date) AS CREATE TEMP TABLE films_recent ON COMMIT DROP AS EXECUTE recentfilms('2002-01-01'); + + + Here is an example of a query plan when the data into the created table can + be filled by the workers in parallel: + + +EXPLAIN CREATE TABLE bar AS SELECT * FROM foo WHERE i > 5; + + QUERY PLAN +-------------------------------------------------------------------&zwsp;-- +Gather (cost=0.00..23.28 rows=850 width=4) + Workers Planned: 2 + -> Create bar + -> Parallel Seq Scan on foo (cost=0.00..23.28 rows=354 width=4) + Filter: (i > 5) +(5 rows) + + + diff --git a/src/test/regress/expected/write_parallel.out b/src/test/regress/expected/write_parallel.out index 0c4da2591a..38a18c5a9b 100644 --- a/src/test/regress/expected/write_parallel.out +++ b/src/test/regress/expected/write_parallel.out @@ -76,4 +76,563 @@ 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 queries won't necessarily get as many workers as the planner +-- asked for. This affects not only the "Workers Launched:" field of EXPLAIN +-- results, but also row counts and loop counts for parallel scans, Gathers, +-- and everything in between. This function filters out the values we can't +-- rely on to be stable. +-- This removes enough info that you might wonder why bother with EXPLAIN +-- ANALYZE at all. The answer is that we need to see whether the parallel +-- inserts are being done by the workers, the only way is that +-- Create <> appears in the explain output. +create function explain_pictas(text) returns setof text +language plpgsql as +$$ +declare + ln text; +begin + for ln in + execute format('explain (analyze, costs off, summary off, timing off) %s', + $1) + loop + ln := regexp_replace(ln, 'Workers Launched: \d+', 'Workers Launched: N'); + ln := regexp_replace(ln, 'actual rows=\d+ loops=\d+', 'actual rows=N loops=N'); + ln := regexp_replace(ln, 'Rows Removed by Filter: \d+', 'Rows Removed by Filter: N'); + return next ln; + end loop; +end; +$$; +-- parallel inserts must occur as the CTAS creates a normal table +select explain_pictas( +'create table parallel_write as select length(stringu1) from tenk1;'); + explain_pictas +---------------------------------------------------------- + Gather (actual rows=N loops=N) + Workers Planned: 4 + Workers Launched: N + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=N loops=N) +(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 +select explain_pictas( +'create temporary table parallel_write as select length(stringu1) from tenk1;'); + explain_pictas +---------------------------------------------------------- + Gather (actual rows=N loops=N) + Workers Planned: 4 + Workers Launched: N + -> Parallel Seq Scan on tenk1 (actual rows=N loops=N) +(4 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must occur as the CTAS creates an unlogged table +select explain_pictas( +'create unlogged table parallel_write as select length(stringu1) from tenk1;'); + explain_pictas +---------------------------------------------------------- + Gather (actual rows=N loops=N) + Workers Planned: 4 + Workers Launched: N + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=N loops=N) +(5 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must occur as the select into creates a normal table +select explain_pictas( +'select length(stringu1) into parallel_write from tenk1;'); + explain_pictas +---------------------------------------------------------- + Gather (actual rows=N loops=N) + Workers Planned: 4 + Workers Launched: N + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=N loops=N) +(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 +select explain_pictas( +'select length(stringu1) into temporary parallel_write from tenk1;'); + explain_pictas +---------------------------------------------------------- + Gather (actual rows=N loops=N) + Workers Planned: 4 + Workers Launched: N + -> Parallel Seq Scan on tenk1 (actual rows=N loops=N) +(4 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must occur as the select into creates an unlogged table +select explain_pictas( +'select length(stringu1) into unlogged parallel_write from tenk1;'); + explain_pictas +---------------------------------------------------------- + Gather (actual rows=N loops=N) + Workers Planned: 4 + Workers Launched: N + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=N loops=N) +(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 +select explain_pictas( +'create table parallel_write as select length(stringu1) from tenk1 for update;'); + explain_pictas +------------------------------------------------- + LockRows (actual rows=N loops=N) + -> Seq Scan on tenk1 (actual rows=N loops=N) +(2 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +drop table parallel_write; +-- parallel inserts must occur as the materialized view is being created here +select explain_pictas( +'create materialized view parallel_mat_view as + select length(stringu1) from tenk1;'); + explain_pictas +---------------------------------------------------------- + Gather (actual rows=N loops=N) + Workers Planned: 4 + Workers Launched: N + -> Create parallel_mat_view + -> Parallel Seq Scan on tenk1 (actual rows=N loops=N) +(5 rows) + +select count(*) from parallel_mat_view; + count +------- + 10000 +(1 row) + +drop materialized view parallel_mat_view; +-- parallel inserts must occur as the CTAS creates the table using prepared +-- statement for which parallelism would have been picked +prepare parallel_write_prep as select length(stringu1) from tenk1; +select explain_pictas( +'create table parallel_write as execute parallel_write_prep;'); + explain_pictas +---------------------------------------------------------- + Gather (actual rows=N loops=N) + Workers Planned: 4 + Workers Launched: N + -> Create parallel_write + -> Parallel Seq Scan on tenk1 (actual rows=N loops=N) +(5 rows) + +select count(*) from parallel_write; + count +------- + 10000 +(1 row) + +deallocate parallel_write_prep; +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; +select explain_pictas( +E'create table parallel_write as + select nextval(\'parallel_write_sequence\'), four from tenk1;'); + explain_pictas +------------------------------------------- + Seq Scan on tenk1 (actual rows=N loops=N) +(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 +select explain_pictas( +'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;'); + explain_pictas +------------------------------------------------------------------------ + Gather (actual rows=N loops=N) + Workers Planned: 4 + Params Evaluated: $1 + Workers Launched: N + -> Create parallel_write + InitPlan 1 (returns $1) + -> Limit (actual rows=N loops=N) + -> Gather (actual rows=N loops=N) + Workers Planned: 4 + Workers Launched: N + -> Parallel Seq Scan on tenk2 (actual rows=N loops=N) + -> Parallel Seq Scan on tenk1 (actual rows=N loops=N) + Filter: (four = 3) + Rows Removed by Filter: N +(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 +select explain_pictas( +'create table parallel_write as select two col1, + (select tenk1.two from generate_series(1,1)) col2 + from tenk1 where tenk1.four = 3;'); + explain_pictas +------------------------------------------------------------------ + Gather (actual rows=N loops=N) + Workers Planned: 4 + Workers Launched: N + -> Parallel Seq Scan on tenk1 (actual rows=N loops=N) + Filter: (four = 3) + Rows Removed by Filter: N + SubPlan 1 + -> Function Scan on generate_series (actual rows=N loops=N) +(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 +select explain_pictas( +'create table parallel_write as select * from temp1 limit 4;'); + explain_pictas +---------------------------------------------------------------- + Limit (actual rows=N loops=N) + -> Gather (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Parallel Seq Scan on temp1 (actual rows=N loops=N) +(5 rows) + +select count(*) from parallel_write; + count +------- + 4 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur, as there is an order by clause +select explain_pictas( +'create table parallel_write as select * from temp1 order by 1;'); + explain_pictas +---------------------------------------------------------------- + Gather Merge (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Sort (actual rows=N loops=N) + 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=N loops=N) +(10 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur, as there is an order by clause +select explain_pictas( +'create table parallel_write as select * from temp1 order by 1;'); + explain_pictas +---------------------------------------------------------------- + Gather Merge (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Sort (actual rows=N loops=N) + 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=N loops=N) +(10 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur, as there is a distinct clause +select explain_pictas( +'create table parallel_write as select distinct * from temp1;'); + explain_pictas +---------------------------------------------------------------- + HashAggregate (actual rows=N loops=N) + Group Key: col1 + Batches: 1 Memory Usage: 40kB + -> Gather (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Parallel Seq Scan on temp1 (actual rows=N loops=N) +(7 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur, as there is an aggregate and group clause +select explain_pictas( +'create table parallel_write as select count(*) from temp1 group by col1;'); + explain_pictas +---------------------------------------------------------------------- + Finalize HashAggregate (actual rows=N loops=N) + Group Key: col1 + Batches: 1 Memory Usage: 40kB + -> Gather (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Partial HashAggregate (actual rows=N loops=N) + 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=N loops=N) +(13 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur, as there is an aggregate, group and having +-- clauses +select explain_pictas( +'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;'); + explain_pictas +---------------------------------------------------------------------------------- + Finalize GroupAggregate (actual rows=N loops=N) + Group Key: ($1) + Filter: (count(temp1.col1) > 0) + InitPlan 1 (returns $1) + -> Limit (actual rows=N loops=N) + -> Gather (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Parallel Seq Scan on temp3 (actual rows=N loops=N) + -> Gather (actual rows=N loops=N) + Workers Planned: 3 + Params Evaluated: $1 + Workers Launched: N + -> Partial GroupAggregate (actual rows=N loops=N) + Group Key: $1 + -> Parallel Hash Join (actual rows=N loops=N) + Hash Cond: (temp1.col1 = temp2.col2) + -> Parallel Seq Scan on temp1 (actual rows=N loops=N) + -> Parallel Hash (actual rows=N loops=N) + Buckets: 4096 Batches: 1 Memory Usage: 64kB + -> Parallel Seq Scan on temp2 (actual rows=N loops=N) +(21 rows) + +select count(*) from parallel_write; + count +------- + 1 +(1 row) + +drop table parallel_write; +-- parallel inserts must not occur, as there is a window function +select explain_pictas( +'create table parallel_write as + select avg(col1) OVER (PARTITION BY col1) from temp1;'); + explain_pictas +---------------------------------------------------------------------- + WindowAgg (actual rows=N loops=N) + -> Gather Merge (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Sort (actual rows=N loops=N) + 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=N loops=N) +(11 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +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; +select explain_pictas( +'create table parallel_write as + select * from temp1, temp2 where temp1.col1 = temp2.col2;'); + explain_pictas +---------------------------------------------------------------------- + Nested Loop (actual rows=N loops=N) + Join Filter: (temp1.col1 = temp2.col2) + Rows Removed by Join Filter: 20 + -> Gather (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Parallel Seq Scan on temp1 (actual rows=N loops=N) + -> Materialize (actual rows=N loops=N) + -> Gather (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Parallel Seq Scan on temp2 (actual rows=N loops=N) +(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; +select explain_pictas( +'create table parallel_write as + select * from temp1, temp2 where temp1.col1 = temp2.col2;'); + explain_pictas +---------------------------------------------------------------------- + Gather (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Create parallel_write + -> Merge Join (actual rows=N loops=N) + Merge Cond: (temp1.col1 = temp2.col2) + -> Sort (actual rows=N loops=N) + 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=N loops=N) + -> Sort (actual rows=N loops=N) + Sort Key: temp2.col2 + Sort Method: quicksort Memory: 25kB + -> Seq Scan on temp2 (actual rows=N loops=N) +(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; +select explain_pictas( +'create table parallel_write as + select * from temp1, temp2 where temp1.col1 = temp2.col2;'); + explain_pictas +---------------------------------------------------------------------- + Gather (actual rows=N loops=N) + Workers Planned: 3 + Workers Launched: N + -> Create parallel_write + -> Parallel Hash Join (actual rows=N loops=N) + Hash Cond: (temp1.col1 = temp2.col2) + -> Parallel Seq Scan on temp1 (actual rows=N loops=N) + -> Parallel Hash (actual rows=N loops=N) + Buckets: 4096 Batches: 1 Memory Usage: 64kB + -> Parallel Seq Scan on temp2 (actual rows=N loops=N) +(10 rows) + +select count(*) from parallel_write; + count +------- + 5 +(1 row) + +drop table parallel_write; +reset enable_nestloop; +reset enable_mergejoin; +reset enable_hashjoin; +drop table temp1; +drop table temp2; +drop table temp3; +drop function explain_pictas(text); rollback; diff --git a/src/test/regress/sql/write_parallel.sql b/src/test/regress/sql/write_parallel.sql index 78b479cedf..40aadafc2a 100644 --- a/src/test/regress/sql/write_parallel.sql +++ b/src/test/regress/sql/write_parallel.sql @@ -39,4 +39,215 @@ 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 queries won't necessarily get as many workers as the planner +-- asked for. This affects not only the "Workers Launched:" field of EXPLAIN +-- results, but also row counts and loop counts for parallel scans, Gathers, +-- and everything in between. This function filters out the values we can't +-- rely on to be stable. +-- This removes enough info that you might wonder why bother with EXPLAIN +-- ANALYZE at all. The answer is that we need to see whether the parallel +-- inserts are being done by the workers, the only way is that +-- Create <> appears in the explain output. +create function explain_pictas(text) returns setof text +language plpgsql as +$$ +declare + ln text; +begin + for ln in + execute format('explain (analyze, costs off, summary off, timing off) %s', + $1) + loop + ln := regexp_replace(ln, 'Workers Launched: \d+', 'Workers Launched: N'); + ln := regexp_replace(ln, 'actual rows=\d+ loops=\d+', 'actual rows=N loops=N'); + ln := regexp_replace(ln, 'Rows Removed by Filter: \d+', 'Rows Removed by Filter: N'); + return next ln; + end loop; +end; +$$; + +-- parallel inserts must occur as the CTAS creates a normal table +select explain_pictas( +'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 +select explain_pictas( +'create temporary table parallel_write as select length(stringu1) from tenk1;'); +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must occur as the CTAS creates an unlogged table +select explain_pictas( +'create unlogged table parallel_write as select length(stringu1) from tenk1;'); +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must occur as the select into creates a normal table +select explain_pictas( +'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 +select explain_pictas( +'select length(stringu1) into temporary parallel_write from tenk1;'); +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must occur as the select into creates an unlogged table +select explain_pictas( +'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 +select explain_pictas( +'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 as the materialized view is being created here +select explain_pictas( +'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 as the CTAS creates the table using prepared +-- statement for which parallelism would have been picked +prepare parallel_write_prep as select length(stringu1) from tenk1; +select explain_pictas( +'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 not occur as the parallelism will not be picked +-- for select part because of the parallel unsafe function +create sequence parallel_write_sequence; +select explain_pictas( +E'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 +select explain_pictas( +'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 +select explain_pictas( +'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 +select explain_pictas( +'create table parallel_write as select * from temp1 limit 4;'); +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur, as there is an order by clause +select explain_pictas( +'create table parallel_write as select * from temp1 order by 1;'); +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur, as there is an order by clause +select explain_pictas( +'create table parallel_write as select * from temp1 order by 1;'); +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur, as there is a distinct clause +select explain_pictas( +'create table parallel_write as select distinct * from temp1;'); +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur, as there is an aggregate and group clause +select explain_pictas( +'create table parallel_write as select count(*) from temp1 group by col1;'); +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur, as there is an aggregate, group and having +-- clauses +select explain_pictas( +'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;'); +select count(*) from parallel_write; +drop table parallel_write; + +-- parallel inserts must not occur, as there is a window function +select explain_pictas( +'create table parallel_write as + select avg(col1) OVER (PARTITION BY col1) from temp1;'); +select count(*) from parallel_write; +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; + +select explain_pictas( +'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; + +select explain_pictas( +'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; + +select explain_pictas( +'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; + +drop table temp1; +drop table temp2; +drop table temp3; +drop function explain_pictas(text); rollback; -- 2.25.1