Skip to content

Pass 2: the planner chooses the segment grid - #634

Draft
zzylol wants to merge 1 commit into
stack/windows-3-pricingfrom
stack/windows-4-segment-grid
Draft

zzylol wants to merge 1 commit into
stack/windows-3-pricingfrom
stack/windows-4-segment-grid

Conversation

@zzylol

@zzylol zzylol commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Stack: #574 → #620 → #618 → #621 → #627 → #625 → #628 → #632 → #634 → #616 → #617 → #622 → #624 → #629 → #630 → #631 → #633 → #635 → #636 → #637

Problem

The shared-segment rule from #628 (share_window_segments, logical-optimizer Pass 2) offered only one grid: even segments whose width is the gcd of every window's lookback and offset. The planner never compared that grid with alternatives. For Example 3a, splitting only at the windows' own boundaries needs 4 segments instead of 5.

Changes (Q67)

  • Two segmentations, each its own Stage 1 variant; Stage 3's cost picks one.
    • (a) Split only at the queries' distinct range boundaries. In 3a the boundaries are 0, 1, 2, 3 and 5 years back, which gives 4 segments, the oldest one 2 years wide.
    • (b) The even gcd grid. In 3a that is 5 one-year segments. It is offered only when it differs from (a); identical segmentations are deduplicated.
    • Labels: · shared segments ×4 and · shared segments ×5. A target's label lists uneven widths, for example Kll · 365d+365d+365d+730d segments. An even grid keeps the old label, 365d segments.
  • WindowForm::Segments { unit_ms, ends }: the grid unit plus a bitmask of where each segment ends, so WindowForm stays Copy. WindowForm::widths gives the pane widths. tumbling_state and the W2 coverage proof (panes_cover_window) now take widths, so panes no longer need equal widths.
  • Sharing::WindowSegments { segments } carries the number of distinct segments, which also keeps the two variants distinct.
  • Accuracy is unchanged: every segment is sized for the group's strictest reader, and merging disjoint KLLs is exact.
  • Stage 2 (materialization.rs): a SummaryMerge over panes of different widths is not a stream of panes, because no pane is an older pane shifted back. Its chain is therefore neither maintained at ingestion time nor kept. In 4a only the even grid has an ingestion-time option.
  • Tests changed for the two grids: pattern_a_shares_four_boundary_or_five_one_year_segments (both forms, their ends masks and labels; 4 or 5 builds and 5 merges after composition), identical_segmentations_are_offered_once (new), stage1_a_shared_segments_serve_all_five (both candidates; each query's segments sum to its range), stage3_a_selects_the_cheaper_segment_grid (new), stage2_a_segments_are_built_once_for_all_consumers (4 and 5 segments, once and monthly), and the example4a_* devtools test (489 plans; only ×5 is maintained at ingestion time).
  • tools/dag-viewer/examples.json: the 3a and 4a stories are updated. planner-layering-example1.json is unchanged (verified by regenerating it).

Costs of each segmentation (after #632's pricing)

Ex ×4 boundary split ×5 even 1-year grid Selected
3a P487 18,104.003889 P488 18,104.004444 P487 ×4
4a P487 25.1444498 (query time; no ingestion-time option) P488 25.1444506; P488-m1 (ingestion time) 1,536.68 P487 ×4

The two grids cost almost the same. Under #632's pricing each row of the scan lands in exactly one segment, so the range and build work is the same for both. The ×4 grid wins only because its merges read fewer states: 4+1+1+1+2 instead of 5+1+1+1+3. Shared input costs 25,112 (3a) and 34.878 (4a).

Test plan

  • cargo fmt --all --check, cargo clippy --workspace --all-targets -D warnings
  • cargo test --workspace: 1692 passed, 0 failed, 13 ignored (after the rebase on main d4869a7; was 1681 passed, 13 ignored)
  • tools/dag-viewer: python3 -m unittest test_viewer: 25 OK
  • Ran stage_pipeline for all six examples. Only the 3a and 4a selections change (to ×4).

Stacked on #632 (stack/windows-3-pricing).

🤖 Generated with Claude Code

The shared-segment rule (Q60) offered one fixed grid, the gcd of every
window's lookback and offset. It now offers two segmentations, each as
its own Stage 1 variant, and Stage 3's cost decides:

- split only at the windows' own boundaries (fewest segments); for
  Example 3a four segments, the oldest two years wide;
- the even gcd grid (3a: five 1-year segments), when it differs.

WindowForm::Segments carries the grid unit and a bitmask of where each
segment ends, so a target's segments may differ in width; tumbling_state
and the coverage proof take the widths. Sharing::WindowSegments carries
the number of distinct segments, labeled "· shared segments ×4" / "×5".
Each segment is still sized for the group's strictest reader.

Stage 2 does not maintain a merge of panes of different widths at
ingestion time or keep it: it is no stream of panes. So in 4a only the
even grid has an ingestion-time option.

Example 3a and 4a select the four boundary segments: they build the same
rows as the five 1-year ones and merge fewer states (3a: 18,104.0039 vs
18,104.0044 per second).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zzylol
zzylol force-pushed the stack/windows-3-pricing branch from 44291c9 to 9cf2956 Compare October 5, 2026 06:21
@zzylol
zzylol force-pushed the stack/windows-4-segment-grid branch from 8d5052f to 1397f2e Compare October 5, 2026 06:21
This was referenced Oct 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant