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;
|
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
|
* populate generic path information
|
||||||
*/
|
*/
|
||||||
|
@ -1545,6 +1551,12 @@ ColumnarScanPath_PlanCustomPath(PlannerInfo *root,
|
||||||
cscan->scan.plan.targetlist = list_copy(tlist);
|
cscan->scan.plan.targetlist = list_copy(tlist);
|
||||||
cscan->scan.scanrelid = best_path->path.parent->relid;
|
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;
|
return (Plan *) cscan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,12 @@ CreateCitusCustomScanPath(PlannerInfo *root, RelOptInfo *relOptInfo,
|
||||||
path->custom_path.path.pathtarget = relOptInfo->reltarget;
|
path->custom_path.path.pathtarget = relOptInfo->reltarget;
|
||||||
path->custom_path.path.parent = relOptInfo;
|
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
|
* 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.
|
* improved in accuracy to produce better plans.
|
||||||
|
|
|
@ -1369,7 +1369,14 @@ FinalizePlan(PlannedStmt *localPlan, DistributedPlan *distributedPlan)
|
||||||
Node *distributedPlanData = (Node *) distributedPlan;
|
Node *distributedPlanData = (Node *) distributedPlan;
|
||||||
|
|
||||||
customScan->custom_private = list_make1(distributedPlanData);
|
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;
|
customScan->flags = CUSTOMPATH_SUPPORT_BACKWARD_SCAN;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fast path queries cannot have any subplans by definition, so skip
|
* 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
|
Columnar Projected Columns: a
|
||||||
(9 rows)
|
(9 rows)
|
||||||
|
|
||||||
SELECT plan_without_arrows($Q$
|
|
||||||
EXPLAIN (costs off, timing off, summary off)
|
EXPLAIN (costs off, timing off, summary off)
|
||||||
SELECT y, * FROM another_columnar_table;
|
SELECT y, * FROM another_columnar_table;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_arrows
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Custom Scan (ColumnarScan) on another_columnar_table
|
Custom Scan (ColumnarScan) on another_columnar_table
|
||||||
Columnar Projected Columns: x, y
|
Columnar Projected Columns: x, y
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
SELECT plan_without_arrows($Q$
|
|
||||||
EXPLAIN (costs off, timing off, summary off)
|
EXPLAIN (costs off, timing off, summary off)
|
||||||
SELECT *, x FROM another_columnar_table;
|
SELECT *, x FROM another_columnar_table;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_arrows
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Custom Scan (ColumnarScan) on another_columnar_table
|
Custom Scan (ColumnarScan) on another_columnar_table
|
||||||
Columnar Projected Columns: x, y
|
Columnar Projected Columns: x, y
|
||||||
|
|
|
@ -958,15 +958,13 @@ SELECT * FROM weird_col_explain;
|
||||||
(7 rows)
|
(7 rows)
|
||||||
|
|
||||||
\set VERBOSITY terse
|
\set VERBOSITY terse
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS OFF, SUMMARY OFF)
|
EXPLAIN (COSTS OFF, SUMMARY OFF)
|
||||||
SELECT *, "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb"
|
SELECT *, "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb"
|
||||||
FROM weird_col_explain
|
FROM weird_col_explain
|
||||||
WHERE "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb" * 2 >
|
WHERE "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb" * 2 >
|
||||||
"aaaaaaaaaaaa$aaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'aaaaaaaa'$a'!";
|
"aaaaaaaaaaaa$aaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'aaaaaaaa'$a'!";
|
||||||
$Q$);
|
|
||||||
NOTICE: identifier "aaaaaaaaaaaa$aaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'aaaaaaaa'$a'!" will be truncated to "aaaaaaaaaaaa$aaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'aaaaaaaa'$a'"
|
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)
|
Custom Scan (Citus Adaptive)
|
||||||
Task Count: 4
|
Task Count: 4
|
||||||
|
|
|
@ -1261,10 +1261,8 @@ NOTICE: copying the data has completed
|
||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
explain (costs off) insert into table_with_sequences select y, x from table_with_sequences;
|
explain (costs off) insert into table_with_sequences select y, x from table_with_sequences;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Custom Scan (Citus INSERT ... SELECT)
|
Custom Scan (Citus INSERT ... SELECT)
|
||||||
INSERT/SELECT method: pull to coordinator
|
INSERT/SELECT method: pull to coordinator
|
||||||
|
@ -1289,10 +1287,8 @@ NOTICE: copying the data has completed
|
||||||
|
|
||||||
(1 row)
|
(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;
|
explain (costs off) insert into table_with_user_sequences select y, x from table_with_user_sequences;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Custom Scan (Citus INSERT ... SELECT)
|
Custom Scan (Citus INSERT ... SELECT)
|
||||||
INSERT/SELECT method: pull to coordinator
|
INSERT/SELECT method: pull to coordinator
|
||||||
|
|
|
@ -1261,10 +1261,8 @@ NOTICE: copying the data has completed
|
||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
explain (costs off) insert into table_with_sequences select y, x from table_with_sequences;
|
explain (costs off) insert into table_with_sequences select y, x from table_with_sequences;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Custom Scan (Citus INSERT ... SELECT)
|
Custom Scan (Citus INSERT ... SELECT)
|
||||||
INSERT/SELECT method: pull to coordinator
|
INSERT/SELECT method: pull to coordinator
|
||||||
|
@ -1289,10 +1287,8 @@ NOTICE: copying the data has completed
|
||||||
|
|
||||||
(1 row)
|
(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;
|
explain (costs off) insert into table_with_user_sequences select y, x from table_with_user_sequences;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Custom Scan (Citus INSERT ... SELECT)
|
Custom Scan (Citus INSERT ... SELECT)
|
||||||
INSERT/SELECT method: pull to coordinator
|
INSERT/SELECT method: pull to coordinator
|
||||||
|
|
|
@ -3,6 +3,13 @@
|
||||||
--
|
--
|
||||||
-- Tests select distinct, and select distinct on features.
|
-- 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;
|
ANALYZE lineitem_hash_part;
|
||||||
-- function calls are supported
|
-- function calls are supported
|
||||||
SELECT DISTINCT l_orderkey, now() FROM lineitem_hash_part LIMIT 0;
|
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
|
-- check the plan if the hash aggreate is disabled. We expect to see sort+unique
|
||||||
-- instead of aggregate plan node to handle distinct.
|
-- instead of aggregate plan node to handle distinct.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT count(*)
|
SELECT DISTINCT count(*)
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Unique
|
Unique
|
||||||
-> Sort
|
-> Sort
|
||||||
|
@ -382,15 +387,13 @@ EXPLAIN (COSTS FALSE)
|
||||||
-- check the plan if the hash aggreate is disabled. Similar to the explain of
|
-- check the plan if the hash aggreate is disabled. Similar to the explain of
|
||||||
-- the query above.
|
-- the query above.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT l_suppkey, count(*)
|
SELECT DISTINCT l_suppkey, count(*)
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Limit
|
Limit
|
||||||
-> Unique
|
-> Unique
|
||||||
|
@ -443,9 +446,10 @@ EXPLAIN (COSTS FALSE)
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Limit
|
Limit
|
||||||
-> Unique
|
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: remote_scan.l_suppkey, ((pg_catalog.sum(remote_scan.avg) / pg_catalog.sum(remote_scan.avg_1)))
|
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
|
-> HashAggregate
|
||||||
Group Key: remote_scan.l_suppkey, remote_scan.worker_column_4
|
Group Key: remote_scan.l_suppkey, remote_scan.worker_column_4
|
||||||
-> Custom Scan (Citus Adaptive)
|
-> Custom Scan (Citus Adaptive)
|
||||||
|
@ -456,20 +460,18 @@ EXPLAIN (COSTS FALSE)
|
||||||
-> HashAggregate
|
-> HashAggregate
|
||||||
Group Key: l_suppkey, l_linenumber
|
Group Key: l_suppkey, l_linenumber
|
||||||
-> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part
|
-> 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
|
-- 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.
|
-- to a bug right now, expectation must be corrected after fixing it.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT l_suppkey, avg(l_partkey)
|
SELECT DISTINCT l_suppkey, avg(l_partkey)
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY 1,2
|
ORDER BY 1,2
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Limit
|
Limit
|
||||||
-> Unique
|
-> Unique
|
||||||
|
@ -539,15 +541,13 @@ EXPLAIN (COSTS FALSE)
|
||||||
-- check the plan if the hash aggreate is disabled. We expect to see sort+unique to
|
-- check the plan if the hash aggreate is disabled. We expect to see sort+unique to
|
||||||
-- handle distinct on.
|
-- handle distinct on.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT ON (l_suppkey) avg(l_partkey)
|
SELECT DISTINCT ON (l_suppkey) avg(l_partkey)
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY l_suppkey,1
|
ORDER BY l_suppkey,1
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Limit
|
Limit
|
||||||
-> Unique
|
-> Unique
|
||||||
|
@ -598,9 +598,10 @@ EXPLAIN (COSTS FALSE)
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Limit
|
Limit
|
||||||
-> Unique
|
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: ((sum(remote_scan.avg) / (pg_catalog.sum(remote_scan.avg_1))::double precision))
|
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
|
-> HashAggregate
|
||||||
Group Key: remote_scan.worker_column_3, remote_scan.worker_column_4
|
Group Key: remote_scan.worker_column_3, remote_scan.worker_column_4
|
||||||
-> Custom Scan (Citus Adaptive)
|
-> Custom Scan (Citus Adaptive)
|
||||||
|
@ -611,20 +612,18 @@ EXPLAIN (COSTS FALSE)
|
||||||
-> HashAggregate
|
-> HashAggregate
|
||||||
Group Key: l_suppkey, l_linenumber
|
Group Key: l_suppkey, l_linenumber
|
||||||
-> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part
|
-> 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
|
-- 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.
|
-- to a bug right now, expectation must be corrected after fixing it.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT avg(ceil(l_partkey / 2))
|
SELECT DISTINCT avg(ceil(l_partkey / 2))
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Limit
|
Limit
|
||||||
-> Unique
|
-> Unique
|
||||||
|
@ -675,9 +674,10 @@ EXPLAIN (COSTS FALSE)
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Limit
|
Limit
|
||||||
-> Unique
|
|
||||||
-> Sort
|
-> Sort
|
||||||
Sort Key: (((pg_catalog.sum(remote_scan.dis))::bigint + COALESCE((pg_catalog.sum(remote_scan.dis_1))::bigint, '0'::bigint)))
|
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
|
-> HashAggregate
|
||||||
Group Key: remote_scan.worker_column_3, remote_scan.worker_column_4
|
Group Key: remote_scan.worker_column_3, remote_scan.worker_column_4
|
||||||
-> Custom Scan (Citus Adaptive)
|
-> Custom Scan (Citus Adaptive)
|
||||||
|
@ -688,20 +688,18 @@ EXPLAIN (COSTS FALSE)
|
||||||
-> HashAggregate
|
-> HashAggregate
|
||||||
Group Key: l_suppkey, l_linenumber
|
Group Key: l_suppkey, l_linenumber
|
||||||
-> Seq Scan on lineitem_hash_part_360041 lineitem_hash_part
|
-> 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
|
-- 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.
|
-- to a bug right now, expectation must be corrected after fixing it.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT sum(l_suppkey) + count(l_partkey) AS dis
|
SELECT DISTINCT sum(l_suppkey) + count(l_partkey) AS dis
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Limit
|
Limit
|
||||||
-> Unique
|
-> Unique
|
||||||
|
@ -910,14 +908,12 @@ EXPLAIN (COSTS FALSE)
|
||||||
|
|
||||||
-- check the plan if the hash aggreate is disabled
|
-- check the plan if the hash aggreate is disabled
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT ceil(count(case when l_partkey > 100000 THEN 1 ELSE 0 END) / 2) AS count
|
SELECT DISTINCT ceil(count(case when l_partkey > 100000 THEN 1 ELSE 0 END) / 2) AS count
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey
|
GROUP BY l_suppkey
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Unique
|
Unique
|
||||||
-> Sort
|
-> Sort
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,15 +17,10 @@ BEGIN
|
||||||
END;
|
END;
|
||||||
$$LANGUAGE plpgsql;
|
$$LANGUAGE plpgsql;
|
||||||
-- Create a function to ignore worker plans in explain output
|
-- 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)
|
CREATE OR REPLACE FUNCTION coordinator_plan(explain_command text, out query_plan text)
|
||||||
RETURNS SETOF TEXT AS $$
|
RETURNS SETOF TEXT AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
FOR query_plan IN execute explain_command LOOP
|
FOR query_plan IN execute explain_command LOOP
|
||||||
IF (query_plan LIKE '%-> Result%' OR query_plan = 'Result')
|
|
||||||
THEN
|
|
||||||
CONTINUE;
|
|
||||||
END IF;
|
|
||||||
RETURN next;
|
RETURN next;
|
||||||
IF query_plan LIKE '%Task Count:%'
|
IF query_plan LIKE '%Task Count:%'
|
||||||
THEN
|
THEN
|
||||||
|
@ -36,16 +31,12 @@ BEGIN
|
||||||
END; $$ language plpgsql;
|
END; $$ language plpgsql;
|
||||||
-- Create a function to ignore worker plans in explain output
|
-- Create a function to ignore worker plans in explain output
|
||||||
-- It also shows task count for plan and subplans
|
-- 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)
|
CREATE OR REPLACE FUNCTION coordinator_plan_with_subplans(explain_command text, out query_plan text)
|
||||||
RETURNS SETOF TEXT AS $$
|
RETURNS SETOF TEXT AS $$
|
||||||
DECLARE
|
DECLARE
|
||||||
task_count_line_reached boolean := false;
|
task_count_line_reached boolean := false;
|
||||||
BEGIN
|
BEGIN
|
||||||
FOR query_plan IN execute explain_command LOOP
|
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
|
IF NOT task_count_line_reached THEN
|
||||||
RETURN next;
|
RETURN next;
|
||||||
END IF;
|
END IF;
|
||||||
|
@ -59,19 +50,6 @@ BEGIN
|
||||||
END LOOP;
|
END LOOP;
|
||||||
RETURN;
|
RETURN;
|
||||||
END; $$ language plpgsql;
|
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 a function to normalize Memory Usage, Buckets, Batches
|
||||||
CREATE OR REPLACE FUNCTION plan_normalize_memory(explain_command text, out query_plan text)
|
CREATE OR REPLACE FUNCTION plan_normalize_memory(explain_command text, out query_plan text)
|
||||||
RETURNS SETOF TEXT AS $$
|
RETURNS SETOF TEXT AS $$
|
||||||
|
@ -81,18 +59,6 @@ BEGIN
|
||||||
RETURN NEXT;
|
RETURN NEXT;
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END; $$ language plpgsql;
|
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)
|
-- 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)
|
CREATE OR REPLACE FUNCTION explain_has_is_not_null(explain_command text)
|
||||||
RETURNS BOOLEAN AS $$
|
RETURNS BOOLEAN AS $$
|
||||||
|
|
|
@ -1491,12 +1491,10 @@ LIMIT 5;
|
||||||
(17 rows)
|
(17 rows)
|
||||||
|
|
||||||
-- Grouping can be pushed down with aggregates even when window function can't
|
-- Grouping can be pushed down with aggregates even when window function can't
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT user_id, count(value_1), stddev(value_1), count(user_id) OVER (PARTITION BY random())
|
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;
|
FROM users_table GROUP BY user_id HAVING avg(value_1) > 2 LIMIT 1;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Limit
|
Limit
|
||||||
-> WindowAgg
|
-> WindowAgg
|
||||||
|
|
|
@ -1495,12 +1495,10 @@ LIMIT 5;
|
||||||
(18 rows)
|
(18 rows)
|
||||||
|
|
||||||
-- Grouping can be pushed down with aggregates even when window function can't
|
-- Grouping can be pushed down with aggregates even when window function can't
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT user_id, count(value_1), stddev(value_1), count(user_id) OVER (PARTITION BY random())
|
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;
|
FROM users_table GROUP BY user_id HAVING avg(value_1) > 2 LIMIT 1;
|
||||||
$Q$);
|
QUERY PLAN
|
||||||
plan_without_result_lines
|
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
Limit
|
Limit
|
||||||
-> WindowAgg
|
-> WindowAgg
|
||||||
|
|
|
@ -130,15 +130,11 @@ INSERT INTO another_columnar_table SELECT generate_series(0,5);
|
||||||
EXPLAIN (analyze on, costs off, timing off, summary off)
|
EXPLAIN (analyze on, costs off, timing off, summary off)
|
||||||
SELECT a, y FROM multi_column_chunk_filtering, another_columnar_table WHERE x > 1;
|
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)
|
EXPLAIN (costs off, timing off, summary off)
|
||||||
SELECT y, * FROM another_columnar_table;
|
SELECT y, * FROM another_columnar_table;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
SELECT plan_without_arrows($Q$
|
|
||||||
EXPLAIN (costs off, timing off, summary off)
|
EXPLAIN (costs off, timing off, summary off)
|
||||||
SELECT *, x FROM another_columnar_table;
|
SELECT *, x FROM another_columnar_table;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
EXPLAIN (costs off, timing off, summary off)
|
EXPLAIN (costs off, timing off, summary off)
|
||||||
SELECT y, another_columnar_table FROM another_columnar_table;
|
SELECT y, another_columnar_table FROM another_columnar_table;
|
||||||
|
|
|
@ -429,13 +429,11 @@ EXPLAIN (COSTS OFF, SUMMARY OFF)
|
||||||
SELECT * FROM weird_col_explain;
|
SELECT * FROM weird_col_explain;
|
||||||
|
|
||||||
\set VERBOSITY terse
|
\set VERBOSITY terse
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS OFF, SUMMARY OFF)
|
EXPLAIN (COSTS OFF, SUMMARY OFF)
|
||||||
SELECT *, "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb"
|
SELECT *, "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb"
|
||||||
FROM weird_col_explain
|
FROM weird_col_explain
|
||||||
WHERE "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb" * 2 >
|
WHERE "bbbbbbbbbbbbbbbbbbbbbbbbb\!bbbb'bbbbbbbbbbbbbbbbbbbbb''bbbbbbbb" * 2 >
|
||||||
"aaaaaaaaaaaa$aaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'aaaaaaaa'$a'!";
|
"aaaaaaaaaaaa$aaaaaa$$aaaaaaaaaaaaaaaaaaaaaaaaaaaaa'aaaaaaaa'$a'!";
|
||||||
$Q$);
|
|
||||||
\set VERBOSITY default
|
\set VERBOSITY default
|
||||||
|
|
||||||
-- should not project any columns
|
-- should not project any columns
|
||||||
|
|
|
@ -635,9 +635,7 @@ DO UPDATE SET
|
||||||
create table table_with_sequences (x int, y int, z bigserial);
|
create table table_with_sequences (x int, y int, z bigserial);
|
||||||
insert into table_with_sequences values (1,1);
|
insert into table_with_sequences values (1,1);
|
||||||
select create_distributed_table('table_with_sequences','x');
|
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;
|
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
|
-- verify that we don't report repartitioned insert/select for tables
|
||||||
-- with user-defined sequences.
|
-- 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'));
|
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);
|
insert into table_with_user_sequences values (1,1);
|
||||||
select create_distributed_table('table_with_user_sequences','x');
|
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;
|
explain (costs off) insert into table_with_user_sequences select y, x from table_with_user_sequences;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
-- clean-up
|
-- clean-up
|
||||||
SET client_min_messages TO WARNING;
|
SET client_min_messages TO WARNING;
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
--
|
--
|
||||||
-- Tests select distinct, and select distinct on features.
|
-- 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;
|
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
|
-- check the plan if the hash aggreate is disabled. We expect to see sort+unique
|
||||||
-- instead of aggregate plan node to handle distinct.
|
-- instead of aggregate plan node to handle distinct.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT count(*)
|
SELECT DISTINCT count(*)
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
SET enable_hashagg TO on;
|
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
|
-- check the plan if the hash aggreate is disabled. Similar to the explain of
|
||||||
-- the query above.
|
-- the query above.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT l_suppkey, count(*)
|
SELECT DISTINCT l_suppkey, count(*)
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
SET enable_hashagg TO on;
|
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
|
-- 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.
|
-- to a bug right now, expectation must be corrected after fixing it.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT l_suppkey, avg(l_partkey)
|
SELECT DISTINCT l_suppkey, avg(l_partkey)
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY 1,2
|
ORDER BY 1,2
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
SET enable_hashagg TO on;
|
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
|
-- check the plan if the hash aggreate is disabled. We expect to see sort+unique to
|
||||||
-- handle distinct on.
|
-- handle distinct on.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT ON (l_suppkey) avg(l_partkey)
|
SELECT DISTINCT ON (l_suppkey) avg(l_partkey)
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY l_suppkey,1
|
ORDER BY l_suppkey,1
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
SET enable_hashagg TO on;
|
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
|
-- 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.
|
-- to a bug right now, expectation must be corrected after fixing it.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT avg(ceil(l_partkey / 2))
|
SELECT DISTINCT avg(ceil(l_partkey / 2))
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
SET enable_hashagg TO on;
|
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
|
-- 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.
|
-- to a bug right now, expectation must be corrected after fixing it.
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT sum(l_suppkey) + count(l_partkey) AS dis
|
SELECT DISTINCT sum(l_suppkey) + count(l_partkey) AS dis
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey, l_linenumber
|
GROUP BY l_suppkey, l_linenumber
|
||||||
ORDER BY 1
|
ORDER BY 1
|
||||||
LIMIT 10;
|
LIMIT 10;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
SET enable_hashagg TO on;
|
SET enable_hashagg TO on;
|
||||||
|
|
||||||
|
@ -345,13 +335,11 @@ EXPLAIN (COSTS FALSE)
|
||||||
|
|
||||||
-- check the plan if the hash aggreate is disabled
|
-- check the plan if the hash aggreate is disabled
|
||||||
SET enable_hashagg TO off;
|
SET enable_hashagg TO off;
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT DISTINCT ceil(count(case when l_partkey > 100000 THEN 1 ELSE 0 END) / 2) AS count
|
SELECT DISTINCT ceil(count(case when l_partkey > 100000 THEN 1 ELSE 0 END) / 2) AS count
|
||||||
FROM lineitem_hash_part
|
FROM lineitem_hash_part
|
||||||
GROUP BY l_suppkey
|
GROUP BY l_suppkey
|
||||||
ORDER BY 1;
|
ORDER BY 1;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
SET enable_hashagg TO on;
|
SET enable_hashagg TO on;
|
||||||
|
|
||||||
|
|
|
@ -20,15 +20,10 @@ END;
|
||||||
$$LANGUAGE plpgsql;
|
$$LANGUAGE plpgsql;
|
||||||
|
|
||||||
-- Create a function to ignore worker plans in explain output
|
-- 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)
|
CREATE OR REPLACE FUNCTION coordinator_plan(explain_command text, out query_plan text)
|
||||||
RETURNS SETOF TEXT AS $$
|
RETURNS SETOF TEXT AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
FOR query_plan IN execute explain_command LOOP
|
FOR query_plan IN execute explain_command LOOP
|
||||||
IF (query_plan LIKE '%-> Result%' OR query_plan = 'Result')
|
|
||||||
THEN
|
|
||||||
CONTINUE;
|
|
||||||
END IF;
|
|
||||||
RETURN next;
|
RETURN next;
|
||||||
IF query_plan LIKE '%Task Count:%'
|
IF query_plan LIKE '%Task Count:%'
|
||||||
THEN
|
THEN
|
||||||
|
@ -40,16 +35,12 @@ END; $$ language plpgsql;
|
||||||
|
|
||||||
-- Create a function to ignore worker plans in explain output
|
-- Create a function to ignore worker plans in explain output
|
||||||
-- It also shows task count for plan and subplans
|
-- 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)
|
CREATE OR REPLACE FUNCTION coordinator_plan_with_subplans(explain_command text, out query_plan text)
|
||||||
RETURNS SETOF TEXT AS $$
|
RETURNS SETOF TEXT AS $$
|
||||||
DECLARE
|
DECLARE
|
||||||
task_count_line_reached boolean := false;
|
task_count_line_reached boolean := false;
|
||||||
BEGIN
|
BEGIN
|
||||||
FOR query_plan IN execute explain_command LOOP
|
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
|
IF NOT task_count_line_reached THEN
|
||||||
RETURN next;
|
RETURN next;
|
||||||
END IF;
|
END IF;
|
||||||
|
@ -64,20 +55,6 @@ BEGIN
|
||||||
RETURN;
|
RETURN;
|
||||||
END; $$ language plpgsql;
|
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 a function to normalize Memory Usage, Buckets, Batches
|
||||||
CREATE OR REPLACE FUNCTION plan_normalize_memory(explain_command text, out query_plan text)
|
CREATE OR REPLACE FUNCTION plan_normalize_memory(explain_command text, out query_plan text)
|
||||||
RETURNS SETOF TEXT AS $$
|
RETURNS SETOF TEXT AS $$
|
||||||
|
@ -88,19 +65,6 @@ BEGIN
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END; $$ language plpgsql;
|
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)
|
-- 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)
|
CREATE OR REPLACE FUNCTION explain_has_is_not_null(explain_command text)
|
||||||
RETURNS BOOLEAN AS $$
|
RETURNS BOOLEAN AS $$
|
||||||
|
|
|
@ -576,11 +576,9 @@ ORDER BY user_id, avg(value_1) DESC
|
||||||
LIMIT 5;
|
LIMIT 5;
|
||||||
|
|
||||||
-- Grouping can be pushed down with aggregates even when window function can't
|
-- Grouping can be pushed down with aggregates even when window function can't
|
||||||
SELECT public.plan_without_result_lines($Q$
|
|
||||||
EXPLAIN (COSTS FALSE)
|
EXPLAIN (COSTS FALSE)
|
||||||
SELECT user_id, count(value_1), stddev(value_1), count(user_id) OVER (PARTITION BY random())
|
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;
|
FROM users_table GROUP BY user_id HAVING avg(value_1) > 2 LIMIT 1;
|
||||||
$Q$);
|
|
||||||
|
|
||||||
-- Window function with inlined CTE
|
-- Window function with inlined CTE
|
||||||
WITH cte as (
|
WITH cte as (
|
||||||
|
|
Loading…
Reference in New Issue