Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't walk into Gather subplans if there's no local scan #56

Merged
merged 1 commit into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions expected/parallel.out
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,35 @@ SELECT count(*) from pg_tracing_consume_spans where span_operation='ExecutorRun'
7
(1 row)

CALL clean_spans();
-- Test leaderless parallel query
set parallel_setup_cost=0;
set parallel_tuple_cost=0;
set min_parallel_table_scan_size=0;
set max_parallel_workers_per_gather=2;
set parallel_leader_participation=false;
/*dddbs='postgres.db',traceparent='00-00000000000000000000000000000001-0000000000000001-01'*/ select 1 from pg_class limit 1;
?column?
----------
1
(1 row)

SELECT span_type, span_operation, lvl FROM peek_ordered_spans where trace_id='00000000000000000000000000000001' ORDER BY lvl, span_operation;
span_type | span_operation | lvl
--------------+-----------------------------------+-----
Select query | select $1 from pg_class limit $2; | 1
ExecutorRun | ExecutorRun | 2
Planner | Planner | 2
Limit | Limit | 3
Select query | Worker 0 | 3
Select query | Worker 1 | 3
ExecutorRun | ExecutorRun | 4
ExecutorRun | ExecutorRun | 4
Gather | Gather | 4
SeqScan | SeqScan on pg_class | 5
SeqScan | SeqScan on pg_class | 5
(11 rows)

-- Cleanup
CALL clean_spans();
CALL reset_settings();
4 changes: 4 additions & 0 deletions expected/setup.out
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ AS $$
SET pg_tracing.caller_sample_rate TO DEFAULT;
SET pg_tracing.track_utility TO DEFAULT;
SET pg_tracing.max_parameter_size TO DEFAULT;
SET parallel_setup_cost TO DEFAULT;
SET parallel_tuple_cost TO DEFAULT;
SET min_parallel_table_scan_size TO DEFAULT;
SET max_parallel_workers_per_gather TO DEFAULT;
$$;
CREATE OR REPLACE PROCEDURE reset_pg_tracing_test_table() AS $$
BEGIN
Expand Down
11 changes: 11 additions & 0 deletions sql/parallel.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ SELECT trace_id from pg_tracing_peek_spans group by trace_id;

-- Check number of executor spans
SELECT count(*) from pg_tracing_consume_spans where span_operation='ExecutorRun';
CALL clean_spans();

-- Test leaderless parallel query
set parallel_setup_cost=0;
set parallel_tuple_cost=0;
set min_parallel_table_scan_size=0;
set max_parallel_workers_per_gather=2;
set parallel_leader_participation=false;
/*dddbs='postgres.db',traceparent='00-00000000000000000000000000000001-0000000000000001-01'*/ select 1 from pg_class limit 1;

SELECT span_type, span_operation, lvl FROM peek_ordered_spans where trace_id='00000000000000000000000000000001' ORDER BY lvl, span_operation;

-- Cleanup
CALL clean_spans();
Expand Down
4 changes: 4 additions & 0 deletions sql/setup.sql
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ AS $$
SET pg_tracing.caller_sample_rate TO DEFAULT;
SET pg_tracing.track_utility TO DEFAULT;
SET pg_tracing.max_parameter_size TO DEFAULT;
SET parallel_setup_cost TO DEFAULT;
SET parallel_tuple_cost TO DEFAULT;
SET min_parallel_table_scan_size TO DEFAULT;
SET max_parallel_workers_per_gather TO DEFAULT;
$$;

CREATE OR REPLACE PROCEDURE reset_pg_tracing_test_table() AS $$
Expand Down
37 changes: 35 additions & 2 deletions src/pg_tracing_planstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,36 @@ create_spans_from_custom_scan(CustomScanState *css, planstateTraceContext * plan
return last_end;
}

/*
* Check if the subplan will run or not
*
* With parallel queries, if leader participation is disabled, the leader won't execute the subplans
*/
static bool
is_subplan_executed(PlanState *planstate)
{
if (planstate == NULL)
return false;

switch (nodeTag(planstate))
{
case T_GatherState:
{
GatherState *splanstate = (GatherState *) planstate;

return splanstate->need_to_scan_locally;
}
case T_GatherMerge:
{
GatherMergeState *splanstate = (GatherMergeState *) planstate;

return splanstate->need_to_scan_locally;
}
default:
return true;
}
}

/*
* Walk through the planstate tree generating a node span for each node.
*/
Expand All @@ -295,6 +325,7 @@ create_spans_from_planstate(PlanState *planstate, planstateTraceContext * planst
TimestampTz span_end;
TimestampTz child_end = 0;
bool haschildren = false;
bool subplan_executed = true;

/* The node was never executed, skip it */
if (planstate->instrument == NULL)
Expand Down Expand Up @@ -379,11 +410,13 @@ create_spans_from_planstate(PlanState *planstate, planstateTraceContext * planst
if (haschildren && planstateTraceContext->deparse_ctx)
planstateTraceContext->ancestors = lcons(planstate->plan, planstateTraceContext->ancestors);

/* We only need to walk the subplans if they are executed */
subplan_executed = is_subplan_executed(planstate);
/* Walk the outerplan */
if (outerPlanState(planstate))
if (outerPlanState(planstate) && subplan_executed)
create_spans_from_planstate(outerPlanState(planstate), planstateTraceContext, span_id, query_id, span_start, root_end, latest_end);
/* Walk the innerplan */
if (innerPlanState(planstate))
if (innerPlanState(planstate) && subplan_executed)
create_spans_from_planstate(innerPlanState(planstate), planstateTraceContext, span_id, query_id, span_start, root_end, latest_end);

/* Handle init plans */
Expand Down