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:
955b3e0f9269639fb916cee3dea37aee50b82df0
marcocitus/fix-subplan-local-execution
Naisila Puka 2022-08-31 10:48:01 +03:00 committed by GitHub
parent 24e695ca27
commit 98dcbeb304
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1616 additions and 159 deletions

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 $$

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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 $$

View File

@ -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 (