Skip to content

sp_QuickieStore: @find_high_impact fixes from prod dogfooding - #855

Open
erikdarlingdata wants to merge 3 commits into
fix-ps-mode-dogfoodfrom
fix-hi-mode-dogfood
Open

sp_QuickieStore: @find_high_impact fixes from prod dogfooding#855
erikdarlingdata wants to merge 3 commits into
fix-ps-mode-dogfoodfrom
fix-hi-mode-dogfood

Conversation

@erikdarlingdata

Copy link
Copy Markdown
Owner

What

Stacked on #854 (base = fix-ps-mode-dogfood; will retarget to dev automatically when that merges). Four @find_high_impact changes driven by running the mode against all 114 production databases (72h Query Store windows, 20–65s per run), plus the mode's first test coverage.

1. Absolute total columns in the output

total_cpu_ms, total_duration_ms, total_physical_reads_mb, total_writes_mb, total_memory_mb, total_tempdb_mb, total_rows, max_dop were already computed into #hi_output but never selected — the only sizing a consumer got was per-server shares, which invites the biggest-slice-of-a-small-pie trap (39 of the 114 fleet databases burn under 10% of one core-day, where a 34% cpu_share means almost nothing). Shares answer "how dominant"; the totals answer "how much." During the fleet analysis these had to be scraped out of the resource_metrics XML.

2. Query-hash include/ignore lists are honored

Parsed locally in the mode block (same pattern as #854's PS-mode change), gating a new #hi_eligible staging table that filters before the per-dimension TOP (@top) picks — an ignored hash never consumes a slot, and the freed slot pulls in the next eligible hash (verified live: row count stays ~90 with the filter on). Shares and percentiles still compute over the full workload deliberately: ignoring a query must not change what percent of the server another query consumed. Results are query_hash-grained, so the plan-hash lists remain non-applicable (documented). Motivation: an index-maintenance query held a top-N slot on 114 of 114 production databases with no way to exclude it across runs.

3. Spills/spools diagnostic floored at 1 MB/exec

total_writes_mb > 0 over a large execution count produced spills/spools (0.0 MB/exec) — a verdict with no content. Observed on the very first row of the very first fleet database analyzed.

4. @top is per-dimension — now documented

A default @top = 15 run returns ~80–95 rows (top N per resource dimension, unioned). Correct behavior, surprising output size; one help-text line.

Tests

run_tests.py: 166 → 177 passing (local SQL 2022 container). The 11 new assertions are the mode's first coverage: clean run, summary/detail shape, total_* columns present, zero-value spills diagnostic absent, and bidirectional include/ignore proof against a surfaced hash value.

Prod verification (limited, 4 instances)

Deployed this build under a throwaway name (sp_QuickieStore_pstest) to 4 prod instances, ran @find_high_impact against dune/GTI/bolt/apex, dropped it after (verified gone):

  • totals columns present on all 4; values consistent with the fleet baseline (e.g. bolt's top row = API.GetRegisterAdjustments, 32,221s window CPU at 29.7% share)
  • zero (0.0 MB/exec) diagnostics (baseline run had them on every database)
  • @ignore_query_hashes with the maintenance query's hash: gone on both databases where it had been in the top-N, with the freed slots refilled

🤖 Generated with Claude Code

erikdarlingdata and others added 3 commits August 4, 2026 15:15
Four changes driven by running the mode against all 114 prod databases:

- Add the absolute total columns (total_cpu_ms, total_duration_ms,
  total_physical_reads_mb, total_writes_mb, total_memory_mb,
  total_tempdb_mb, total_rows, max_dop) to the output. They were already
  in #hi_output but never selected, so the only sizing available was
  per-server shares — and a 34% share on a quiet server reads identical
  to a 34% share on a busy one. Shares answer 'how dominant'; the totals
  answer 'how much'. (In the fleet run, 39 of 114 databases burned less
  than 10% of one core-day total.)
- Honor the query-hash include/ignore lists: parsed locally in the mode
  block, gating a new #hi_eligible staging table that filters BEFORE the
  per-dimension TOP picks, so an ignored hash never consumes a slot.
  Shares and percentiles still compute over the full workload on purpose:
  ignoring a query must not change what percent of the server another
  query consumed. Results are query_hash-grained, so the plan-hash lists
  still do not apply. Motivation: an index-maintenance query held a
  top-N slot on 114 of 114 production databases with no way to exclude it.
- Floor the spills/spools diagnostic at 1 MB/exec: total_writes_mb > 0
  over a huge execution count rendered as 'spills/spools (0.0 MB/exec)',
  a verdict with no content.
- Document that @top is per resource dimension (a default run returns
  several times @top rows), which surprised this author in the field.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Eleven new checks: clean default run, summary + detail shape, the
absolute total_* columns present, the zero-value spills diagnostic
staying quiet, and bidirectional query-hash include/ignore proof against
a surfaced hash VALUE in detail rows (ignore removes it, include keeps
only it, a hash nobody has returns zero rows with the summary as
positive control). 177 total.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…te window

The #query_hash_totals aggregation had no date restriction: it summed
every runtime stats row in Query Store history for the hash, and those
all-time numbers sat next to window-scoped columns in the same output
row. On a fleet with weeks of QS retention that inflated the
by_query_hash totals ~7.6x in a 72-hour analysis (live A/B on one
tenant: 110,841s unscoped vs 14,627s scoped for the same hash and
window), which defeats the parameter's whole purpose of gauging a
hash's impact for the period being analyzed.

Same disease and same fix as #850/#852: restrict on
qsrs.last_execution_time to match the date semantics of the main where
clause and the wait sort order joins. Third instance of this pattern.

Also documents the columns as window-scoped in the parameter help.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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