mirror of https://github.com/citusdata/citus.git
Specifies that our CustomScan providers support projections (#6244)
Before, this was the default mode for CustomScan providers. Now, the default is to assume that they can't project. This causes performance penalties due to adding unnecessary Result nodes. Hence we use the newly added flag, CUSTOMPATH_SUPPORT_PROJECTION to get it back to how it was. In PG15 support branch we created explain functions to ignore the new Result nodes, so we undo that in this commit. Relevant PG commit: 955b3e0f9269639fb916cee3dea37aee50b82df0marcocitus/fix-subplan-local-execution
parent
24e695ca27
commit
98dcbeb304
|
@ -1303,6 +1303,12 @@ AddColumnarScanPath(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte,
|
|||
|
||||
cpath->methods = &ColumnarScanPathMethods;
|
||||
|
||||
#if (PG_VERSION_NUM >= PG_VERSION_15)
|
||||
|
||||
/* necessary to avoid extra Result node in PG15 */
|
||||
cpath->flags = CUSTOMPATH_SUPPORT_PROJECTION;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* populate generic path information
|
||||
*/
|
||||
|
@ -1545,6 +1551,12 @@ ColumnarScanPath_PlanCustomPath(PlannerInfo *root,
|
|||
cscan->scan.plan.targetlist = list_copy(tlist);
|
||||
cscan->scan.scanrelid = best_path->path.parent->relid;
|
||||
|
||||
#if (PG_VERSION_NUM >= 150000)
|
||||
|
||||
/* necessary to avoid extra Result node in PG15 */
|
||||
cscan->flags = CUSTOMPATH_SUPPORT_PROJECTION;
|
||||
#endif
|
||||
|
||||
return (Plan *) cscan;
|
||||
}
|
||||
|
||||
|
|
|
@ -136,6 +136,12 @@ CreateCitusCustomScanPath(PlannerInfo *root, RelOptInfo *relOptInfo,
|
|||
path->custom_path.path.pathtarget = relOptInfo->reltarget;
|
||||
path->custom_path.path.parent = relOptInfo;
|
||||
|
||||
#if (PG_VERSION_NUM >= PG_VERSION_15)
|
||||
|
||||
/* necessary to avoid extra Result node in PG15 */
|
||||
path->custom_path.flags = CUSTOMPATH_SUPPORT_PROJECTION;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The 100k rows we put on the cost of the path is kind of arbitrary and could be
|
||||
* improved in accuracy to produce better plans.
|
||||
|
|
|
@ -1369,7 +1369,14 @@ FinalizePlan(PlannedStmt *localPlan, DistributedPlan *distributedPlan)
|
|||
Node *distributedPlanData = (Node *) distributedPlan;
|
||||
|
||||
customScan->custom_private = list_make1(distributedPlanData);
|
||||
|
||||
#if (PG_VERSION_NUM >= PG_VERSION_15)
|
||||
|
||||
/* necessary to avoid extra Result node in PG15 */
|
||||
customScan->flags = CUSTOMPATH_SUPPORT_BACKWARD_SCAN | CUSTOMPATH_SUPPORT_PROJECTION;
|
||||
#else
|
||||
customScan->flags = CUSTOMPATH_SUPPORT_BACKWARD_SCAN;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fast path queries cannot have any subplans by definition, so skip
|
||||
|
|
|
@ -264,21 +264,17 @@ EXPLAIN (analyze on, costs off, timing off, summary off)
|
|||
Columnar Projected Columns: a
|
||||
(9 rows)
|
||||
|
||||
SELECT plan_without_arrows($Q$
|
||||
EXPLAIN (costs off, timing off, summary off)
|
||||
SELECT y, * FROM another_columnar_table;
|
||||
$Q$);
|
||||
plan_without_arrows
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Custom Scan (ColumnarScan) on another_columnar_table
|
||||
Columnar Projected Columns: x, y
|
||||
(2 rows)
|
||||
|
||||
SELECT plan_without_arrows($Q$
|
||||
EXPLAIN (costs off, timing off, summary off)
|
||||
SELECT *, x FROM another_columnar_table;
|
||||
$Q$);
|
||||
plan_without_arrows
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Custom Scan (ColumnarScan) on another_columnar_table
|
||||
Columnar Projected Columns: x, y
|
||||
|
|
|
@ -958,15 +958,13 @@ SELECT * FROM weird_col_explain;
|
|||
(7 rows)
|
||||
|
||||
\set VERBOSITY terse
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS OFF, SUMMARY OFF)
|
||||
SELECT *, "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb"
|
||||
FROM weird_col_explain
|
||||
WHERE "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb" * 2 >
|
||||
"aaaaaaaaaaaa$aaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'aaaaaaaa'$a'!";
|
||||
$Q$);
|
||||
NOTICE: identifier "aaaaaaaaaaaa$aaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'aaaaaaaa'$a'!" will be truncated to "aaaaaaaaaaaa$aaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'aaaaaaaa'$a'"
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Custom Scan (Citus Adaptive)
|
||||
Task Count: 4
|
||||
|
|
|
@ -1261,10 +1261,8 @@ NOTICE: copying the data has completed
|
|||
|
||||
(1 row)
|
||||
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
explain (costs off) insert into table_with_sequences select y, x from table_with_sequences;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Custom Scan (Citus INSERT ... SELECT)
|
||||
INSERT/SELECT method: pull to coordinator
|
||||
|
@ -1289,10 +1287,8 @@ NOTICE: copying the data has completed
|
|||
|
||||
(1 row)
|
||||
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
explain (costs off) insert into table_with_user_sequences select y, x from table_with_user_sequences;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Custom Scan (Citus INSERT ... SELECT)
|
||||
INSERT/SELECT method: pull to coordinator
|
||||
|
|
|
@ -1261,10 +1261,8 @@ NOTICE: copying the data has completed
|
|||
|
||||
(1 row)
|
||||
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
explain (costs off) insert into table_with_sequences select y, x from table_with_sequences;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Custom Scan (Citus INSERT ... SELECT)
|
||||
INSERT/SELECT method: pull to coordinator
|
||||
|
@ -1289,10 +1287,8 @@ NOTICE: copying the data has completed
|
|||
|
||||
(1 row)
|
||||
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
explain (costs off) insert into table_with_user_sequences select y, x from table_with_user_sequences;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Custom Scan (Citus INSERT ... SELECT)
|
||||
INSERT/SELECT method: pull to coordinator
|
||||
|
|
|
@ -3,6 +3,13 @@
|
|||
--
|
||||
-- Tests select distinct, and select distinct on features.
|
||||
--
|
||||
SHOW server_version \gset
|
||||
SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15;
|
||||
server_version_ge_15
|
||||
---------------------------------------------------------------------
|
||||
t
|
||||
(1 row)
|
||||
|
||||
ANALYZE lineitem_hash_part;
|
||||
-- function calls are supported
|
||||
SELECT DISTINCT l_orderkey, now() FROM lineitem_hash_part LIMIT 0;
|
||||
|
@ -306,14 +313,12 @@ EXPLAIN (COSTS FALSE)
|
|||
-- check the plan if the hash aggreate is disabled. We expect to see sort+unique
|
||||
-- instead of aggregate plan node to handle distinct.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT count(*)
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Unique
|
||||
-> Sort
|
||||
|
@ -382,15 +387,13 @@ EXPLAIN (COSTS FALSE)
|
|||
-- check the plan if the hash aggreate is disabled. Similar to the explain of
|
||||
-- the query above.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT l_suppkey, count(*)
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1
|
||||
LIMIT 10;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Limit
|
||||
-> Unique
|
||||
|
@ -440,12 +443,13 @@ EXPLAIN (COSTS FALSE)
|
|||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1,2
|
||||
LIMIT 10;
|
||||
QUERY PLAN
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Limit
|
||||
-> Unique
|
||||
-> Sort
|
||||
Sort Key: remote_scan.l_suppkey, ((pg_catalog.sum(remote_scan.avg) / pg_catalog.sum(remote_scan.avg_1)))
|
||||
-> Sort
|
||||
Sort Key: remote_scan.l_suppkey, ((pg_catalog.sum(remote_scan.avg) / pg_catalog.sum(remote_scan.avg_1)))
|
||||
-> HashAggregate
|
||||
Group Key: remote_scan.l_suppkey, (pg_catalog.sum(remote_scan.avg) / pg_catalog.sum(remote_scan.avg_1))
|
||||
-> HashAggregate
|
||||
Group Key: remote_scan.l_suppkey, remote_scan.worker_column_4
|
||||
-> Custom Scan (Citus Adaptive)
|
||||
|
@ -456,20 +460,18 @@ EXPLAIN (COSTS FALSE)
|
|||
-> HashAggregate
|
||||
Group Key: l_suppkey, l_linenumber
|
||||
-> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part
|
||||
(14 rows)
|
||||
(15 rows)
|
||||
|
||||
-- check the plan if the hash aggreate is disabled. This explain errors out due
|
||||
-- to a bug right now, expectation must be corrected after fixing it.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT l_suppkey, avg(l_partkey)
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1,2
|
||||
LIMIT 10;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Limit
|
||||
-> Unique
|
||||
|
@ -539,15 +541,13 @@ EXPLAIN (COSTS FALSE)
|
|||
-- check the plan if the hash aggreate is disabled. We expect to see sort+unique to
|
||||
-- handle distinct on.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT ON (l_suppkey) avg(l_partkey)
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY l_suppkey,1
|
||||
LIMIT 10;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Limit
|
||||
-> Unique
|
||||
|
@ -595,12 +595,13 @@ EXPLAIN (COSTS FALSE)
|
|||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1
|
||||
LIMIT 10;
|
||||
QUERY PLAN
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Limit
|
||||
-> Unique
|
||||
-> Sort
|
||||
Sort Key: ((sum(remote_scan.avg) / (pg_catalog.sum(remote_scan.avg_1))::double precision))
|
||||
-> Sort
|
||||
Sort Key: ((sum(remote_scan.avg) / (pg_catalog.sum(remote_scan.avg_1))::double precision))
|
||||
-> HashAggregate
|
||||
Group Key: (sum(remote_scan.avg) / (pg_catalog.sum(remote_scan.avg_1))::double precision)
|
||||
-> HashAggregate
|
||||
Group Key: remote_scan.worker_column_3, remote_scan.worker_column_4
|
||||
-> Custom Scan (Citus Adaptive)
|
||||
|
@ -611,20 +612,18 @@ EXPLAIN (COSTS FALSE)
|
|||
-> HashAggregate
|
||||
Group Key: l_suppkey, l_linenumber
|
||||
-> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part
|
||||
(14 rows)
|
||||
(15 rows)
|
||||
|
||||
-- check the plan if the hash aggreate is disabled. This explain errors out due
|
||||
-- to a bug right now, expectation must be corrected after fixing it.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT avg(ceil(l_partkey / 2))
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1
|
||||
LIMIT 10;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Limit
|
||||
-> Unique
|
||||
|
@ -672,12 +671,13 @@ EXPLAIN (COSTS FALSE)
|
|||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1
|
||||
LIMIT 10;
|
||||
QUERY PLAN
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Limit
|
||||
-> Unique
|
||||
-> Sort
|
||||
Sort Key: (((pg_catalog.sum(remote_scan.dis))::bigint + COALESCE((pg_catalog.sum(remote_scan.dis_1))::bigint, '0'::bigint)))
|
||||
-> Sort
|
||||
Sort Key: (((pg_catalog.sum(remote_scan.dis))::bigint + COALESCE((pg_catalog.sum(remote_scan.dis_1))::bigint, '0'::bigint)))
|
||||
-> HashAggregate
|
||||
Group Key: ((pg_catalog.sum(remote_scan.dis))::bigint + COALESCE((pg_catalog.sum(remote_scan.dis_1))::bigint, '0'::bigint))
|
||||
-> HashAggregate
|
||||
Group Key: remote_scan.worker_column_3, remote_scan.worker_column_4
|
||||
-> Custom Scan (Citus Adaptive)
|
||||
|
@ -688,20 +688,18 @@ EXPLAIN (COSTS FALSE)
|
|||
-> HashAggregate
|
||||
Group Key: l_suppkey, l_linenumber
|
||||
-> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part
|
||||
(14 rows)
|
||||
(15 rows)
|
||||
|
||||
-- check the plan if the hash aggreate is disabled. This explain errors out due
|
||||
-- to a bug right now, expectation must be corrected after fixing it.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT sum(l_suppkey) + count(l_partkey) AS dis
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1
|
||||
LIMIT 10;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Limit
|
||||
-> Unique
|
||||
|
@ -910,14 +908,12 @@ EXPLAIN (COSTS FALSE)
|
|||
|
||||
-- check the plan if the hash aggreate is disabled
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT ceil(count(case when l_partkey > 100000 THEN 1 ELSE 0 END) / 2) AS count
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey
|
||||
ORDER BY 1;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Unique
|
||||
-> Sort
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,15 +17,10 @@ BEGIN
|
|||
END;
|
||||
$$LANGUAGE plpgsql;
|
||||
-- Create a function to ignore worker plans in explain output
|
||||
-- Also remove extra "-> Result" lines for PG15 support
|
||||
CREATE OR REPLACE FUNCTION coordinator_plan(explain_command text, out query_plan text)
|
||||
RETURNS SETOF TEXT AS $$
|
||||
BEGIN
|
||||
FOR query_plan IN execute explain_command LOOP
|
||||
IF (query_plan LIKE '%-> Result%' OR query_plan = 'Result')
|
||||
THEN
|
||||
CONTINUE;
|
||||
END IF;
|
||||
RETURN next;
|
||||
IF query_plan LIKE '%Task Count:%'
|
||||
THEN
|
||||
|
@ -36,16 +31,12 @@ BEGIN
|
|||
END; $$ language plpgsql;
|
||||
-- Create a function to ignore worker plans in explain output
|
||||
-- It also shows task count for plan and subplans
|
||||
-- Also remove extra "-> Result" lines for PG15 support
|
||||
CREATE OR REPLACE FUNCTION coordinator_plan_with_subplans(explain_command text, out query_plan text)
|
||||
RETURNS SETOF TEXT AS $$
|
||||
DECLARE
|
||||
task_count_line_reached boolean := false;
|
||||
BEGIN
|
||||
FOR query_plan IN execute explain_command LOOP
|
||||
IF (query_plan LIKE '%-> Result%' OR query_plan = 'Result') THEN
|
||||
CONTINUE;
|
||||
END IF;
|
||||
IF NOT task_count_line_reached THEN
|
||||
RETURN next;
|
||||
END IF;
|
||||
|
@ -59,19 +50,6 @@ BEGIN
|
|||
END LOOP;
|
||||
RETURN;
|
||||
END; $$ language plpgsql;
|
||||
-- Create a function to ignore "-> Result" lines for PG15 support
|
||||
-- In PG15 there are some extra "-> Result" lines
|
||||
CREATE OR REPLACE FUNCTION plan_without_result_lines(explain_command text, out query_plan text)
|
||||
RETURNS SETOF TEXT AS $$
|
||||
BEGIN
|
||||
FOR query_plan IN execute explain_command LOOP
|
||||
IF (query_plan LIKE '%-> Result%' OR query_plan = 'Result') THEN
|
||||
CONTINUE;
|
||||
END IF;
|
||||
RETURN next;
|
||||
END LOOP;
|
||||
RETURN;
|
||||
END; $$ language plpgsql;
|
||||
-- Create a function to normalize Memory Usage, Buckets, Batches
|
||||
CREATE OR REPLACE FUNCTION plan_normalize_memory(explain_command text, out query_plan text)
|
||||
RETURNS SETOF TEXT AS $$
|
||||
|
@ -81,18 +59,6 @@ BEGIN
|
|||
RETURN NEXT;
|
||||
END LOOP;
|
||||
END; $$ language plpgsql;
|
||||
-- Create a function to remove arrows from the explain plan
|
||||
CREATE OR REPLACE FUNCTION plan_without_arrows(explain_command text, out query_plan text)
|
||||
RETURNS SETOF TEXT AS $$
|
||||
BEGIN
|
||||
FOR query_plan IN execute explain_command LOOP
|
||||
IF (query_plan LIKE '%-> Result%' OR query_plan = 'Result') THEN
|
||||
CONTINUE;
|
||||
END IF;
|
||||
query_plan := regexp_replace(query_plan, '( )*-> (.*)', '\2', 'g');
|
||||
RETURN NEXT;
|
||||
END LOOP;
|
||||
END; $$ language plpgsql;
|
||||
-- helper function that returns true if output of given explain has "is not null" (case in-sensitive)
|
||||
CREATE OR REPLACE FUNCTION explain_has_is_not_null(explain_command text)
|
||||
RETURNS BOOLEAN AS $$
|
||||
|
|
|
@ -1491,12 +1491,10 @@ LIMIT 5;
|
|||
(17 rows)
|
||||
|
||||
-- Grouping can be pushed down with aggregates even when window function can't
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT user_id, count(value_1), stddev(value_1), count(user_id) OVER (PARTITION BY random())
|
||||
FROM users_table GROUP BY user_id HAVING avg(value_1) > 2 LIMIT 1;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Limit
|
||||
-> WindowAgg
|
||||
|
|
|
@ -1495,12 +1495,10 @@ LIMIT 5;
|
|||
(18 rows)
|
||||
|
||||
-- Grouping can be pushed down with aggregates even when window function can't
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT user_id, count(value_1), stddev(value_1), count(user_id) OVER (PARTITION BY random())
|
||||
FROM users_table GROUP BY user_id HAVING avg(value_1) > 2 LIMIT 1;
|
||||
$Q$);
|
||||
plan_without_result_lines
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------
|
||||
Limit
|
||||
-> WindowAgg
|
||||
|
|
|
@ -130,15 +130,11 @@ INSERT INTO another_columnar_table SELECT generate_series(0,5);
|
|||
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||
SELECT a, y FROM multi_column_chunk_filtering, another_columnar_table WHERE x > 1;
|
||||
|
||||
SELECT plan_without_arrows($Q$
|
||||
EXPLAIN (costs off, timing off, summary off)
|
||||
SELECT y, * FROM another_columnar_table;
|
||||
$Q$);
|
||||
|
||||
SELECT plan_without_arrows($Q$
|
||||
EXPLAIN (costs off, timing off, summary off)
|
||||
SELECT *, x FROM another_columnar_table;
|
||||
$Q$);
|
||||
|
||||
EXPLAIN (costs off, timing off, summary off)
|
||||
SELECT y, another_columnar_table FROM another_columnar_table;
|
||||
|
|
|
@ -429,13 +429,11 @@ EXPLAIN (COSTS OFF, SUMMARY OFF)
|
|||
SELECT * FROM weird_col_explain;
|
||||
|
||||
\set VERBOSITY terse
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS OFF, SUMMARY OFF)
|
||||
SELECT *, "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb"
|
||||
FROM weird_col_explain
|
||||
WHERE "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb" * 2 >
|
||||
"aaaaaaaaaaaa$aaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'aaaaaaaa'$a'!";
|
||||
$Q$);
|
||||
\set VERBOSITY default
|
||||
|
||||
-- should not project any columns
|
||||
|
|
|
@ -635,9 +635,7 @@ DO UPDATE SET
|
|||
create table table_with_sequences (x int, y int, z bigserial);
|
||||
insert into table_with_sequences values (1,1);
|
||||
select create_distributed_table('table_with_sequences','x');
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
explain (costs off) insert into table_with_sequences select y, x from table_with_sequences;
|
||||
$Q$);
|
||||
|
||||
-- verify that we don't report repartitioned insert/select for tables
|
||||
-- with user-defined sequences.
|
||||
|
@ -645,9 +643,7 @@ CREATE SEQUENCE user_defined_sequence;
|
|||
create table table_with_user_sequences (x int, y int, z bigint default nextval('user_defined_sequence'));
|
||||
insert into table_with_user_sequences values (1,1);
|
||||
select create_distributed_table('table_with_user_sequences','x');
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
explain (costs off) insert into table_with_user_sequences select y, x from table_with_user_sequences;
|
||||
$Q$);
|
||||
|
||||
-- clean-up
|
||||
SET client_min_messages TO WARNING;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
--
|
||||
-- Tests select distinct, and select distinct on features.
|
||||
--
|
||||
SHOW server_version \gset
|
||||
SELECT substring(:'server_version', '\d+')::int >= 15 AS server_version_ge_15;
|
||||
|
||||
ANALYZE lineitem_hash_part;
|
||||
|
||||
|
@ -113,13 +115,11 @@ EXPLAIN (COSTS FALSE)
|
|||
-- check the plan if the hash aggreate is disabled. We expect to see sort+unique
|
||||
-- instead of aggregate plan node to handle distinct.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT count(*)
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1;
|
||||
$Q$);
|
||||
|
||||
SET enable_hashagg TO on;
|
||||
|
||||
|
@ -142,14 +142,12 @@ EXPLAIN (COSTS FALSE)
|
|||
-- check the plan if the hash aggreate is disabled. Similar to the explain of
|
||||
-- the query above.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT l_suppkey, count(*)
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1
|
||||
LIMIT 10;
|
||||
$Q$);
|
||||
|
||||
SET enable_hashagg TO on;
|
||||
|
||||
|
@ -173,14 +171,12 @@ EXPLAIN (COSTS FALSE)
|
|||
-- check the plan if the hash aggreate is disabled. This explain errors out due
|
||||
-- to a bug right now, expectation must be corrected after fixing it.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT l_suppkey, avg(l_partkey)
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1,2
|
||||
LIMIT 10;
|
||||
$Q$);
|
||||
|
||||
SET enable_hashagg TO on;
|
||||
|
||||
|
@ -203,14 +199,12 @@ EXPLAIN (COSTS FALSE)
|
|||
-- check the plan if the hash aggreate is disabled. We expect to see sort+unique to
|
||||
-- handle distinct on.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT ON (l_suppkey) avg(l_partkey)
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY l_suppkey,1
|
||||
LIMIT 10;
|
||||
$Q$);
|
||||
|
||||
SET enable_hashagg TO on;
|
||||
|
||||
|
@ -232,14 +226,12 @@ EXPLAIN (COSTS FALSE)
|
|||
-- check the plan if the hash aggreate is disabled. This explain errors out due
|
||||
-- to a bug right now, expectation must be corrected after fixing it.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT avg(ceil(l_partkey / 2))
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1
|
||||
LIMIT 10;
|
||||
$Q$);
|
||||
|
||||
SET enable_hashagg TO on;
|
||||
|
||||
|
@ -261,14 +253,12 @@ EXPLAIN (COSTS FALSE)
|
|||
-- check the plan if the hash aggreate is disabled. This explain errors out due
|
||||
-- to a bug right now, expectation must be corrected after fixing it.
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT sum(l_suppkey) + count(l_partkey) AS dis
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey, l_linenumber
|
||||
ORDER BY 1
|
||||
LIMIT 10;
|
||||
$Q$);
|
||||
|
||||
SET enable_hashagg TO on;
|
||||
|
||||
|
@ -345,13 +335,11 @@ EXPLAIN (COSTS FALSE)
|
|||
|
||||
-- check the plan if the hash aggreate is disabled
|
||||
SET enable_hashagg TO off;
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT DISTINCT ceil(count(case when l_partkey > 100000 THEN 1 ELSE 0 END) / 2) AS count
|
||||
FROM lineitem_hash_part
|
||||
GROUP BY l_suppkey
|
||||
ORDER BY 1;
|
||||
$Q$);
|
||||
|
||||
SET enable_hashagg TO on;
|
||||
|
||||
|
|
|
@ -20,15 +20,10 @@ END;
|
|||
$$LANGUAGE plpgsql;
|
||||
|
||||
-- Create a function to ignore worker plans in explain output
|
||||
-- Also remove extra "-> Result" lines for PG15 support
|
||||
CREATE OR REPLACE FUNCTION coordinator_plan(explain_command text, out query_plan text)
|
||||
RETURNS SETOF TEXT AS $$
|
||||
BEGIN
|
||||
FOR query_plan IN execute explain_command LOOP
|
||||
IF (query_plan LIKE '%-> Result%' OR query_plan = 'Result')
|
||||
THEN
|
||||
CONTINUE;
|
||||
END IF;
|
||||
RETURN next;
|
||||
IF query_plan LIKE '%Task Count:%'
|
||||
THEN
|
||||
|
@ -40,16 +35,12 @@ END; $$ language plpgsql;
|
|||
|
||||
-- Create a function to ignore worker plans in explain output
|
||||
-- It also shows task count for plan and subplans
|
||||
-- Also remove extra "-> Result" lines for PG15 support
|
||||
CREATE OR REPLACE FUNCTION coordinator_plan_with_subplans(explain_command text, out query_plan text)
|
||||
RETURNS SETOF TEXT AS $$
|
||||
DECLARE
|
||||
task_count_line_reached boolean := false;
|
||||
BEGIN
|
||||
FOR query_plan IN execute explain_command LOOP
|
||||
IF (query_plan LIKE '%-> Result%' OR query_plan = 'Result') THEN
|
||||
CONTINUE;
|
||||
END IF;
|
||||
IF NOT task_count_line_reached THEN
|
||||
RETURN next;
|
||||
END IF;
|
||||
|
@ -64,20 +55,6 @@ BEGIN
|
|||
RETURN;
|
||||
END; $$ language plpgsql;
|
||||
|
||||
-- Create a function to ignore "-> Result" lines for PG15 support
|
||||
-- In PG15 there are some extra "-> Result" lines
|
||||
CREATE OR REPLACE FUNCTION plan_without_result_lines(explain_command text, out query_plan text)
|
||||
RETURNS SETOF TEXT AS $$
|
||||
BEGIN
|
||||
FOR query_plan IN execute explain_command LOOP
|
||||
IF (query_plan LIKE '%-> Result%' OR query_plan = 'Result') THEN
|
||||
CONTINUE;
|
||||
END IF;
|
||||
RETURN next;
|
||||
END LOOP;
|
||||
RETURN;
|
||||
END; $$ language plpgsql;
|
||||
|
||||
-- Create a function to normalize Memory Usage, Buckets, Batches
|
||||
CREATE OR REPLACE FUNCTION plan_normalize_memory(explain_command text, out query_plan text)
|
||||
RETURNS SETOF TEXT AS $$
|
||||
|
@ -88,19 +65,6 @@ BEGIN
|
|||
END LOOP;
|
||||
END; $$ language plpgsql;
|
||||
|
||||
-- Create a function to remove arrows from the explain plan
|
||||
CREATE OR REPLACE FUNCTION plan_without_arrows(explain_command text, out query_plan text)
|
||||
RETURNS SETOF TEXT AS $$
|
||||
BEGIN
|
||||
FOR query_plan IN execute explain_command LOOP
|
||||
IF (query_plan LIKE '%-> Result%' OR query_plan = 'Result') THEN
|
||||
CONTINUE;
|
||||
END IF;
|
||||
query_plan := regexp_replace(query_plan, '( )*-> (.*)', '\2', 'g');
|
||||
RETURN NEXT;
|
||||
END LOOP;
|
||||
END; $$ language plpgsql;
|
||||
|
||||
-- helper function that returns true if output of given explain has "is not null" (case in-sensitive)
|
||||
CREATE OR REPLACE FUNCTION explain_has_is_not_null(explain_command text)
|
||||
RETURNS BOOLEAN AS $$
|
||||
|
|
|
@ -576,11 +576,9 @@ ORDER BY user_id, avg(value_1) DESC
|
|||
LIMIT 5;
|
||||
|
||||
-- Grouping can be pushed down with aggregates even when window function can't
|
||||
SELECT public.plan_without_result_lines($Q$
|
||||
EXPLAIN (COSTS FALSE)
|
||||
SELECT user_id, count(value_1), stddev(value_1), count(user_id) OVER (PARTITION BY random())
|
||||
FROM users_table GROUP BY user_id HAVING avg(value_1) > 2 LIMIT 1;
|
||||
$Q$);
|
||||
|
||||
-- Window function with inlined CTE
|
||||
WITH cte as (
|
||||
|
|
Loading…
Reference in New Issue