EXPLAIN ANALYZE - Prevent execution of the plan during the plan-print
DESCRIPTION: Fixed a bug in EXPLAIN ANALYZE to prevent unintended (duplicate) execution of the plan during the plan-print phase.
Fixes #4212
🐞 Bug #4212 : Redundant (Subplan) Execution in EXPLAIN ANALYZE codepath
🔍 Background
In the standard PostgreSQL execution path, ExplainOnePlan() is responsible for two distinct operations depending on whether EXPLAIN ANALYZE is requested:
-
Execute the plan
if (es->analyze) ExecutorRun(queryDesc, direction, 0L, true); -
Print the plan tree
ExplainPrintPlan(es, queryDesc);
When printing the plan, the executor should not run the plan again. Execution is only expected to happen once—at the top level when es->analyze = true.
⚠️ Issue in Citus
In the Citus implementation of CustomScanMethods.ExplainCustomScan = CitusExplainScan, which is a custom scan explain callback function used to print explain information of a Citus plan incorrectly performs redundant execution inside the explain path of ExplainPrintPlan()
ExplainOnePlan()
ExplainPrintPlan()
ExplainNode()
CitusExplainScan()
if (distributedPlan->subPlanList != NIL)
{
ExplainSubPlans(distributedPlan, es);
{
PlannedStmt *plan = subPlan->plan;
ExplainOnePlan(plan, ...); // ⚠️ May re-execute subplan if es->analyze is true
}
}
This causes the subplans to be executed again, even though they have already been executed during the top-level plan execution. This behavior violates the expectation in PostgreSQL where EXPLAIN ANALYZE should execute each node exactly once for analysis.
✅ Fix (proposed)
To align with PostgreSQL’s expectations and avoid double execution:
es->analyze = false;
es->timing = false;
is now set explicitly in ExplainSubPlans() before recursively calling ExplainOnePlan(). This ensures that subplans are explained for shape only—not executed again.