Skip to content

DAG viewer: list the physical candidates of the selected logical candidate (enumerate materializations) and click one to draw it #1037

Open

Description

@zzylol

Problem, by example

Open Example 1 (1 · dashboard panels) in the Stage Viewer and choose any Stage 1 candidate, for example joint-logical-1. The Stage 2 lane can show exactly one physical candidate for it, joint-plan-1. Measured on main (61ee27f), out/example1.json has:

Section Count
Stage 1 logical candidates 6
Stage 2 physical candidates 6 (one per logical)

You can't see the alternatives for this logical candidate: the same DAG with the shared range built once per evaluation (query time, shared), with Q1's rate panes maintained at ingestion time, or with nothing materialized. You also can't see what each one costs, or why it lost. The old document format showed 72 physical candidates for the same example. The Stage 2 lane has only a candidate dropdown over all physical candidates, not a list for the chosen logical candidate.

Wanted: given the selected logical candidate, the Stage 2 lane lists its physical candidates. Each row shows:

  • id;
  • materialization label (for example ingestion time: Kll for Q1, 5 × 1m panes);
  • cost per second, or ✗ invalid with the reason;
  • ✓ selected on the one the plan uses.

Clicking a row draws that candidate in the Stage 2 lane.

Why it isn't there today

Since the candidate-connection MILP search (#934), stage_pipeline writes "one physical candidate per composed logical candidate" (crates/devtools/src/bin/stage_pipeline.rs, header comment):

  • The MILP chooses each node's Materialization (NotMaterialized, MatAtIngestion, MatAtQuery, kept panes) inside the model.
  • materialize_selected_candidates (crates/plan-selection/src/search/candidates/physical.rs) applies only the chosen assignment.
  • The alternatives the model considered are never written out.

Proposal (decided 2026-10-29: enumerate materializations)

  1. stage_pipeline: for each displayed logical candidate, enumerate the materialization assignments its nodes allow, as the search's candidate inventory offers them.
    • Cap the count with --max-physical-per-logical <n> (default 64), listing the selected assignment first.
    • Run each one through Stage 2 (materialize_selected_candidates / optimize_physical_asap_chosen) and Stage 3 costing and validation.
    • Write each as a Stage 2 candidate with from_logical, display_name, dag, and its cost or rejection.
    • Record per logical candidate how many assignments exist and whether the list is capped.
  2. Viewer: a clickable list in the Stage 2 lane, filtered to the current logical candidate, in the style of the Stage 3 / Enumerated DAGs rows. Clicking a row calls selectPhysical.
  3. Cross-check: no listed valid candidate is cheaper than the selected plan. The same check as --price-enumerated (feat(devtools): stage_pipeline --price-enumerated prices each enumerated memo choice and flags any cheaper than the selected plan #1028).

Scope and acceptance

  • Example 1 shows several physical candidates for the selected logical candidate. Each has a cost or a reason, and exactly one is ✓ selected.
  • Selection results don't change: the same selected plan and cost as main on Examples 1, 3a and 3b and the ratio-of-quantiles example.
  • Tests:
    • a stage_pipeline test for the per-logical enumeration and its cap;
    • node --test tools/dag-viewer/*.test.mjs;
    • python3 -m unittest test_viewer test_server with a test that clicks a row.
  • stage-viewer.md and the README mention the list.

Out of scope: listing physical candidates for enumerated memo DAGs (the Enumerated DAGs panel).

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    dag-viewerDAG export and visualization toolingdev-toolsDeveloper tools, diagnostics, and demosenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions