Skip to content

Release v1.8.0 — Joe feedback E1-E12 batch#274

Merged
erikdarlingdata merged 4 commits into
mainfrom
dev
Apr 24, 2026
Merged

Release v1.8.0 — Joe feedback E1-E12 batch#274
erikdarlingdata merged 4 commits into
mainfrom
dev

Conversation

@erikdarlingdata
Copy link
Copy Markdown
Owner

Summary

Batched release with twelve of Joe's E-items from #215:

Runtime card (PR #270 — E7, E8, E9, E10, E11):

  • E7: title reads "Predicted Runtime" for estimated plans
  • E8: used grant % > 100 now shows red
  • E9: any operator spill forces the grant tier orange, regardless of %
  • E10: ⚠ spill indicator next to Used when anything spilled
  • E11: reorder — Elapsed → CPU:Elapsed → DOP → CPU → Compile → Memory/Used → Optimization → CE Model → Cost

Wait stats (PR #271 — E12):

  • Wait Stats card is a collapsible <details>, default-closed so improvement items aren't pushed below the fold

Cursor rules (PR #272 — E1, E2, E3):

  • Rule 36 Dynamic Cursor — statement-level warning with FAST_FORWARD / STATIC / KEYSET guidance
  • Rule 37 Cursor Missing LOCAL — regex on DECLARE CURSOR without LOCAL, links to Erik's blog
  • Rule 11 Scan With Predicate augmented with dynamic-cursor root-cause text when applicable

Estimated plan info (PR #273 — E4, E5, E6):

  • E6: MemoryGrantResult exposes DesiredKB + SerialRequiredKB; estimated plans show "Memory (estimated)" when the optimizer requested a grant
  • E4 + E5: already rendered when data present; no code change needed

Not in this batch:

  • E13 (%Wait per-operator metric) — design-first, pairs with the per-operator consolidation refactor

Version 1.7.8 → 1.8.0.

🤖 Generated with Claude Code

erikdarlingdata and others added 4 commits April 24, 2026 15:04
- E7: card title is "Predicted Runtime" for estimated plans ("Runtime" for
  actual). Applied on HTML export, web viewer, and Avalonia (via new
  RuntimeSummaryTitle x:Name binding).
- E8: used grant % > 100 is rendered as eff-bad (red) — an over-used grant
  is the opposite of healthy, not green.
- E9: any operator in the plan that spilled to tempdb also forces the grant
  tier to eff-warn at best, regardless of utilization %. A 60%-used grant
  with a spilled sort underneath isn't "good".
- E10: spill indicator appended to the Memory/Used row when any operator
  warning has a type ending in "Spill". Shows as "⚠ spill" (HTML + web use a
  styled .spill-tag span; Avalonia uses plain text suffix).
- E11: Runtime box reordered to Joe's preferred layout —
    Elapsed → CPU:Elapsed → DOP → CPU → Compile → Memory/Used → Optimization
    → CE Model → Cost
  Avalonia keeps its extra rows (UDF, Threads, Cached plan size, Grant wait,
  Early abort) slotted near logical neighbors. Cost moves from first to
  last across all three surfaces. Also adds a CPU:Elapsed row to the Avalonia
  panel (previously only on web and HTML).

New GetMemoryGrantColorClass / MemoryGrantColor helper centralizes the
tiering so the three surfaces stay consistent. HasSpillInTree /
HasSpillInPlanTree walks warnings looking for types that end with " Spill".

Version bump 1.7.8 -> 1.8.0.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wait Stats card now uses <details>/<summary> and defaults to closed so
it doesn't push improvement items below the fold on 1080p monitors.

- Web viewer (Index.razor): insight-card switches to <details> element.
  app.css styles .insight-card > summary the same as h4, hides the native
  disclosure marker, and shows ▸ / ▾ chevrons tied to the [open] attribute.
- HTML export (HtmlExporter.cs): same pattern on the .card.waits card.

Keeps the chart as a complementary view (Joe's earlier preference) — just
out of the way by default. Click the header to expand.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Rule 36 — Dynamic Cursor (E1): statement-level warning when CursorActualType
is "Dynamic". Dynamic cursors can't use many indexes because they must
tolerate data changes between fetches; recommends FAST_FORWARD / STATIC /
KEYSET as the usual fix.

Rule 37 — Cursor Missing LOCAL (E3): regex-scans statement text for
DECLARE <name> [qualifiers] CURSOR FOR without LOCAL in the qualifier list.
Default cursor scope is GLOBAL which bloats the plan cache — links to
Erik's blog post on OPENJSON cursor declarations.

Rule 11 augmentation (E2): when Scan With Predicate fires on a statement
whose CursorActualType is Dynamic, the message now points at the cursor as
the root cause instead of suggesting more indexes. Verified on Joe's plan
P7opX79MzB — the clustered-index-scan warning now reads "This query is
running inside a dynamic cursor, which can prevent index usage; changing
the cursor type often fixes scans like this without any indexing change."

No regressions on non-cursor plans (c1-c5.sqlplan, 20260415_1.sqlplan).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- E6: MemoryGrantResult now exposes DesiredKB (optimizer's pre-execution
  parallel-adjusted desired grant) and SerialRequiredKB. When QueryTime is
  null (estimated plan) but DesiredKB > 0, the Runtime card shows a "Memory
  (estimated)" row with the desired grant, plus a "Serial required" row
  when it differs. Applied to HTML export + web viewer.

- E4: compile time already renders on estimated plans when CompileTimeMs > 0
  (existing behavior). Joe's cursor plan legitimately has compile_time=0 on
  its inner cursor ops, so nothing displays there. No code change needed.

- E5: predicted DOP already shows on estimated plans when DegreeOfParallelism
  > 0 (existing behavior). Plans with no DOP show the Serial reason. Host
  EstimatedAvailableDOP from OptimizerHardwareDependentProperties intentionally
  not surfaced — it describes the host, not the plan, and is misleading for
  plans the optimizer explicitly kept serial.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@erikdarlingdata erikdarlingdata merged commit 194d1fc into main Apr 24, 2026
3 checks passed
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