Merge pull request #1888 from citusdata/subplan_explain

Show distributed subplan ID in EXPLAIN output
pull/1883/head
Marco Slot 2017-12-19 22:13:11 +03:00 committed by GitHub
commit 393e625cb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 210 additions and 26 deletions

View File

@ -72,7 +72,7 @@ typedef struct RemoteExplainPlan
/* Explain functions for distributed queries */ /* Explain functions for distributed queries */
static void ExplainSubPlans(List *subPlanList, ExplainState *es); static void ExplainSubPlans(DistributedPlan *distributedPlan, ExplainState *es);
static void ExplainJob(Job *job, ExplainState *es); static void ExplainJob(Job *job, ExplainState *es);
static void ExplainMapMergeJob(MapMergeJob *mapMergeJob, ExplainState *es); static void ExplainMapMergeJob(MapMergeJob *mapMergeJob, ExplainState *es);
static void ExplainTaskList(List *taskList, ExplainState *es); static void ExplainTaskList(List *taskList, ExplainState *es);
@ -127,7 +127,7 @@ CitusExplainScan(CustomScanState *node, List *ancestors, struct ExplainState *es
if (distributedPlan->subPlanList != NIL) if (distributedPlan->subPlanList != NIL)
{ {
ExplainSubPlans(distributedPlan->subPlanList, es); ExplainSubPlans(distributedPlan, es);
} }
ExplainJob(distributedPlan->workerJob, es); ExplainJob(distributedPlan->workerJob, es);
@ -179,20 +179,14 @@ CoordinatorInsertSelectExplainScan(CustomScanState *node, List *ancestors,
* planning time and set it to 0. * planning time and set it to 0.
*/ */
static void static void
ExplainSubPlans(List *subPlanList, ExplainState *es) ExplainSubPlans(DistributedPlan *distributedPlan, ExplainState *es)
{ {
ListCell *subPlanCell = NULL; ListCell *subPlanCell = NULL;
uint64 planId = distributedPlan->planId;
ExplainOpenGroup("Subplans", "Subplans", false, es); ExplainOpenGroup("Subplans", "Subplans", false, es);
if (es->format == EXPLAIN_FORMAT_TEXT) foreach(subPlanCell, distributedPlan->subPlanList)
{
appendStringInfoSpaces(es->str, es->indent * 2);
appendStringInfo(es->str, "-> Distributed Subplan\n");
es->indent += 3;
}
foreach(subPlanCell, subPlanList)
{ {
DistributedSubPlan *subPlan = (DistributedSubPlan *) lfirst(subPlanCell); DistributedSubPlan *subPlan = (DistributedSubPlan *) lfirst(subPlanCell);
PlannedStmt *plan = subPlan->plan; PlannedStmt *plan = subPlan->plan;
@ -201,6 +195,15 @@ ExplainSubPlans(List *subPlanList, ExplainState *es)
char *queryString = NULL; char *queryString = NULL;
instr_time planduration; instr_time planduration;
if (es->format == EXPLAIN_FORMAT_TEXT)
{
char *resultId = GenerateResultId(planId, subPlan->subPlanId);
appendStringInfoSpaces(es->str, es->indent * 2);
appendStringInfo(es->str, "-> Distributed Subplan %s\n", resultId);
es->indent += 3;
}
/* set the planning time to 0 */ /* set the planning time to 0 */
INSTR_TIME_SET_CURRENT(planduration); INSTR_TIME_SET_CURRENT(planduration);
INSTR_TIME_SUBTRACT(planduration, planduration); INSTR_TIME_SUBTRACT(planduration, planduration);
@ -210,11 +213,11 @@ ExplainSubPlans(List *subPlanList, ExplainState *es)
#else #else
ExplainOnePlan(plan, into, es, queryString, params, &planduration); ExplainOnePlan(plan, into, es, queryString, params, &planduration);
#endif #endif
}
if (es->format == EXPLAIN_FORMAT_TEXT) if (es->format == EXPLAIN_FORMAT_TEXT)
{ {
es->indent -= 3; es->indent -= 3;
}
} }
ExplainCloseGroup("Subplans", "Subplans", false, es); ExplainCloseGroup("Subplans", "Subplans", false, es);

View File

@ -140,6 +140,17 @@ RecursivelyPlanSubqueriesAndCTEs(Query *query,
DeferredErrorMessage *error = NULL; DeferredErrorMessage *error = NULL;
RecursivePlanningContext context; RecursivePlanningContext context;
context.level = 0;
context.planId = planId;
context.subPlanList = NIL;
context.plannerRestrictionContext = plannerRestrictionContext;
error = RecursivelyPlanCTEs(query, &context);
if (error != NULL)
{
return error;
}
if (SubqueryPushdown) if (SubqueryPushdown)
{ {
/* /*
@ -155,17 +166,6 @@ RecursivelyPlanSubqueriesAndCTEs(Query *query,
return NULL; return NULL;
} }
context.level = 0;
context.planId = planId;
context.subPlanList = NIL;
context.plannerRestrictionContext = plannerRestrictionContext;
error = RecursivelyPlanCTEs(query, &context);
if (error != NULL)
{
return error;
}
/* XXX: plan subqueries */ /* XXX: plan subqueries */
*subPlanList = context.subPlanList; *subPlanList = context.subPlanList;

View File

@ -713,6 +713,7 @@ Limit
Sort Key: events.event_time DESC Sort Key: events.event_time DESC
-> Seq Scan on events_1400029 events -> Seq Scan on events_1400029 events
Filter: (composite_id = users.composite_id) Filter: (composite_id = users.composite_id)
RESET citus.subquery_pushdown;
-- Test all tasks output -- Test all tasks output
SET citus.explain_all_tasks TO on; SET citus.explain_all_tasks TO on;
EXPLAIN (COSTS FALSE) EXPLAIN (COSTS FALSE)
@ -1115,3 +1116,75 @@ Custom Scan (Citus INSERT ... SELECT via coordinator)
-> Append -> Append
-> Function Scan on generate_series s -> Function Scan on generate_series s
-> Function Scan on generate_series s_1 -> Function Scan on generate_series s_1
-- explain with recursive planning
EXPLAIN (COSTS OFF, VERBOSE true)
WITH keys AS (
SELECT DISTINCT l_orderkey FROM lineitem_hash_part
),
series AS (
SELECT s FROM generate_series(1,10) s
)
SELECT l_orderkey FROM series JOIN keys ON (s = l_orderkey)
ORDER BY s;
Custom Scan (Citus Router)
Output: remote_scan.l_orderkey
-> Distributed Subplan 54_1
-> HashAggregate
Output: remote_scan.l_orderkey
Group Key: remote_scan.l_orderkey
-> Custom Scan (Citus Real-Time)
Output: remote_scan.l_orderkey
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=57637 dbname=regression
-> HashAggregate
Output: l_orderkey
Group Key: lineitem_hash_part.l_orderkey
-> Seq Scan on public.lineitem_hash_part_360038 lineitem_hash_part
Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment
-> Distributed Subplan 54_2
-> Function Scan on pg_catalog.generate_series s
Output: s
Function Call: generate_series(1, 10)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=localhost port=57638 dbname=regression
-> Merge Join
Output: intermediate_result_1.l_orderkey, intermediate_result.s
Merge Cond: (intermediate_result.s = intermediate_result_1.l_orderkey)
-> Sort
Output: intermediate_result.s
Sort Key: intermediate_result.s
-> Function Scan on pg_catalog.read_intermediate_result intermediate_result
Output: intermediate_result.s
Function Call: read_intermediate_result('54_2'::text, 'binary'::citus_copy_format)
-> Sort
Output: intermediate_result_1.l_orderkey
Sort Key: intermediate_result_1.l_orderkey
-> Function Scan on pg_catalog.read_intermediate_result intermediate_result_1
Output: intermediate_result_1.l_orderkey
Function Call: read_intermediate_result('54_1'::text, 'binary'::citus_copy_format)
SELECT true AS valid FROM explain_json($$
WITH result AS (
SELECT l_quantity, count(*) count_quantity FROM lineitem
GROUP BY l_quantity ORDER BY count_quantity, l_quantity
),
series AS (
SELECT s FROM generate_series(1,10) s
)
SELECT * FROM result JOIN series ON (s = count_quantity) JOIN orders_hash_part ON (s = o_orderkey)
$$);
t
SELECT true AS valid FROM explain_xml($$
WITH result AS (
SELECT l_quantity, count(*) count_quantity FROM lineitem
GROUP BY l_quantity ORDER BY count_quantity, l_quantity
),
series AS (
SELECT s FROM generate_series(1,10) s
)
SELECT * FROM result JOIN series ON (s = l_quantity) JOIN orders_hash_part ON (s = o_orderkey)
$$);
t

View File

@ -713,6 +713,7 @@ Limit
Sort Key: events.event_time DESC Sort Key: events.event_time DESC
-> Seq Scan on events_1400029 events -> Seq Scan on events_1400029 events
Filter: (composite_id = users.composite_id) Filter: (composite_id = users.composite_id)
RESET citus.subquery_pushdown;
-- Test all tasks output -- Test all tasks output
SET citus.explain_all_tasks TO on; SET citus.explain_all_tasks TO on;
EXPLAIN (COSTS FALSE) EXPLAIN (COSTS FALSE)
@ -1115,3 +1116,75 @@ Custom Scan (Citus INSERT ... SELECT via coordinator)
-> Append -> Append
-> Function Scan on generate_series s -> Function Scan on generate_series s
-> Function Scan on generate_series s_1 -> Function Scan on generate_series s_1
-- explain with recursive planning
EXPLAIN (COSTS OFF, VERBOSE true)
WITH keys AS (
SELECT DISTINCT l_orderkey FROM lineitem_hash_part
),
series AS (
SELECT s FROM generate_series(1,10) s
)
SELECT l_orderkey FROM series JOIN keys ON (s = l_orderkey)
ORDER BY s;
Custom Scan (Citus Router)
Output: remote_scan.l_orderkey
-> Distributed Subplan 54_1
-> HashAggregate
Output: remote_scan.l_orderkey
Group Key: remote_scan.l_orderkey
-> Custom Scan (Citus Real-Time)
Output: remote_scan.l_orderkey
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=57637 dbname=regression
-> HashAggregate
Output: l_orderkey
Group Key: lineitem_hash_part.l_orderkey
-> Seq Scan on public.lineitem_hash_part_360038 lineitem_hash_part
Output: l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment
-> Distributed Subplan 54_2
-> Function Scan on pg_catalog.generate_series s
Output: s
Function Call: generate_series(1, 10)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=localhost port=57638 dbname=regression
-> Merge Join
Output: intermediate_result_1.l_orderkey, intermediate_result.s
Merge Cond: (intermediate_result.s = intermediate_result_1.l_orderkey)
-> Sort
Output: intermediate_result.s
Sort Key: intermediate_result.s
-> Function Scan on pg_catalog.read_intermediate_result intermediate_result
Output: intermediate_result.s
Function Call: read_intermediate_result('54_2'::text, 'binary'::citus_copy_format)
-> Sort
Output: intermediate_result_1.l_orderkey
Sort Key: intermediate_result_1.l_orderkey
-> Function Scan on pg_catalog.read_intermediate_result intermediate_result_1
Output: intermediate_result_1.l_orderkey
Function Call: read_intermediate_result('54_1'::text, 'binary'::citus_copy_format)
SELECT true AS valid FROM explain_json($$
WITH result AS (
SELECT l_quantity, count(*) count_quantity FROM lineitem
GROUP BY l_quantity ORDER BY count_quantity, l_quantity
),
series AS (
SELECT s FROM generate_series(1,10) s
)
SELECT * FROM result JOIN series ON (s = count_quantity) JOIN orders_hash_part ON (s = o_orderkey)
$$);
t
SELECT true AS valid FROM explain_xml($$
WITH result AS (
SELECT l_quantity, count(*) count_quantity FROM lineitem
GROUP BY l_quantity ORDER BY count_quantity, l_quantity
),
series AS (
SELECT s FROM generate_series(1,10) s
)
SELECT * FROM result JOIN series ON (s = l_quantity) JOIN orders_hash_part ON (s = o_orderkey)
$$);
t

View File

@ -356,6 +356,8 @@ ORDER BY
LIMIT LIMIT
10; 10;
RESET citus.subquery_pushdown;
-- Test all tasks output -- Test all tasks output
SET citus.explain_all_tasks TO on; SET citus.explain_all_tasks TO on;
@ -519,3 +521,36 @@ EXPLAIN (COSTS OFF)
INSERT INTO lineitem_hash_part INSERT INTO lineitem_hash_part
( SELECT s FROM generate_series(1,5) s) UNION ( SELECT s FROM generate_series(1,5) s) UNION
( SELECT s FROM generate_series(5,10) s); ( SELECT s FROM generate_series(5,10) s);
-- explain with recursive planning
EXPLAIN (COSTS OFF, VERBOSE true)
WITH keys AS (
SELECT DISTINCT l_orderkey FROM lineitem_hash_part
),
series AS (
SELECT s FROM generate_series(1,10) s
)
SELECT l_orderkey FROM series JOIN keys ON (s = l_orderkey)
ORDER BY s;
SELECT true AS valid FROM explain_json($$
WITH result AS (
SELECT l_quantity, count(*) count_quantity FROM lineitem
GROUP BY l_quantity ORDER BY count_quantity, l_quantity
),
series AS (
SELECT s FROM generate_series(1,10) s
)
SELECT * FROM result JOIN series ON (s = count_quantity) JOIN orders_hash_part ON (s = o_orderkey)
$$);
SELECT true AS valid FROM explain_xml($$
WITH result AS (
SELECT l_quantity, count(*) count_quantity FROM lineitem
GROUP BY l_quantity ORDER BY count_quantity, l_quantity
),
series AS (
SELECT s FROM generate_series(1,10) s
)
SELECT * FROM result JOIN series ON (s = l_quantity) JOIN orders_hash_part ON (s = o_orderkey)
$$);