Choose an explain-specialized PlanExplainer at the factory instead of the isExplain constructor flag

    • Type: Improvement
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • Query Optimization
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Overview

      Since PR 10gen/mongo#58846, PlanExplainerImpl takes an isExplain constructor flag (src/mongo/db/query/plan_explainer_impl.cpp, constructor): for explain commands whose MultiPlanStage stays in the execution tree (pure multi-planning), the constructor snapshots the trial statistics before the explained query executes, so the V3 winner display can show trial rather than final-execution counters; normal queries skip that stats-tree deep copy. Review (jameseh96 on PR 10gen/mongo#58846) suggested making this structural instead of flag-driven: the factory is the natural customization point to choose a different PlanExplainer instance, and the V3 machinery could live in its own subclass.

      Proposed fix

      • Explain-ness is known before the explainer is constructed (query.getExplain()), so plan_explainer_factory::make() (src/mongo/db/query/plan_explainer_factory.cpp) can choose between:
        • an explain-specialized subclass (e.g. PlanExplainerImplV3 deriving from PlanExplainerImpl) that owns the construction-time trial-stats snapshot and the V3 per-plan enumerator (_getPlanEntriesV3() becoming a virtual override), and
        • the lean base implementation for normal queries, with no isExplain flag and no snapshot.
      • The "fallback to legacy" cases keep working through the base-class implementation - either the factory picks the base class when legacy shape is known ahead of construction, or the subclass delegates to the parent implementation when the decision arrives later.
      • Delete the isExplain parameter from the constructor and from plan_explainer_factory::make(), including the pass-through in PlanExplainerClassicRuntimePlannerForSBE (src/mongo/db/query/plan_explainer_sbe.cpp), whose embedded classic explainer serves only the legacy accessors and never needs the snapshot.

      Note: a pure no-op explainer for non-explain operations is not viable - getPlanSummary()/getSummaryStats() serve every query (slow-query log, profiler, CurOp) - so the split is between "explain-capable" and "summary-only" surfaces, not "explainer vs nothing".

      Sequencing

      Do this after SERVER-131451 (V3 output for the planSummary/plannerChoice verbosities): that work reshapes the V3 surface the subclass would own, and carving the class boundary before it means carving it twice.

      TODO SERVER-NNNNN comments referencing this ticket sit on the PlanExplainerImpl constructor and the factory.

            Assignee:
            Unassigned
            Reporter:
            Timour Katchaounov
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: