citus icon indicating copy to clipboard operation
citus copied to clipboard

EXPLAIN ANALYZE - Prevent execution of the plan during the plan-print

Open tejeswarm opened this issue 8 months ago • 1 comments

DESCRIPTION: Fixed a bug in EXPLAIN ANALYZE to prevent unintended (duplicate) execution of the (sub)plans during the explain 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:

  1. Execute the plan

    if (es->analyze)
        ExecutorRun(queryDesc, direction, 0L, true);
    
  2. 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)

Save the output of Subplans during ExecuteSubPlans(), and later use it in ExplainSubPlans()

tejeswarm avatar Jun 10 '25 02:06 tejeswarm