#2760 removed both hints believing ~4,237ms of avg CPU on one prod
database was compile cost. That was inferred from a telemetry signature
(high CPU, 381 logical reads, 18 rows), never measured. The cost was the
live Query Store catalog-view joins, which #2764 fixed by staging them
into temps.
Measured compile for the post-#2764 payload, SET STATISTICS TIME ON
against SQL Server 2025: ~84ms CPU total across all five statements
(50 + 13 + 6 + 4 + 11), and that is a ceiling -- taken under emulation.
The hints are back for their real reason: plan cache hygiene. This body
runs once per database, per server, every cycle, so caching a plan for
each accumulates cache bulk fleet-wide for plans nobody reuses.
#2764's staging is untouched: four #pm_plan_correction_* temps, the
EXISTS-gated SELECT INTOs, and the shipping SELECT joining temps rather
than catalog views all verified unchanged against the built assembly.
Fixes #2766.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Fixes #2766.
Problem
PR #2762 removed
OPTION(RECOMPILE)from both statements inPlanCorrectionCollector.PayloadBodyText, attributing ~4,237ms of avg CPU onmulti-45/Demoto compile cost.That attribution was never verified. It was inferred from a telemetry signature — high CPU against 381 logical reads and 18 rows — with nothing isolating compile time from execution time. The actual cost was the live Query Store catalog-view joins in the shipping SELECT, which PR #2765 then replaced with staged temps. Staging fixed it; removing RECOMPILE never addressed it.
Measurement
SET STATISTICS TIME ONagainst SQL Server 2025, currentdevpayload text — compile CPU per statement: 50 + 13 + 6 + 4 + 11 = 84ms total, clean, no errors. Taken on a Rosetta-emulated container, so 84ms is a ceiling; real hardware compiles faster.Fix
OPTION(RECOMPILE)restored to the two statements #2762 removed it from, in the post-#2765 query shape — for plan cache hygiene, not performance. This body runs once per database, per server, every cycle; caching a plan for each accumulates cache bulk across the fleet for plans nobody reuses. At ~84ms total, keeping them out of cache costs effectively nothing.Doc comment rewritten to state that reason and correct the record, so the same "optimization" isn't attempted again.
PayloadBody_DoesNotCarryRecompile(added by #2762) asserted the opposite of intended behavior and is replaced byPayloadBody_CarriesRecompile_ForPlanCacheHygiene, which anchors each hint to its own statement rather than a bareContains— the enumeration query carries its own RECOMPILE and would otherwise mask a regression — and pins the payload count at exactly 2. The regexes use\s*across the newline because the source is CRLF on disk.#2765's materialization is untouched
Verified against the built assembly (not source) with a throwaway
net10.0harness:Pin proven red without the fix: against
9168e75c(pre-changedev) the same three RECOMPILE assertions all fail — payload RECOMPILE count 0, both statement anchors unmatched.What the harness did not cover: it inspects the generated SQL text and structure, not execution. The Windows-only
Lite.Testssuite is CI's job. No live-target execution of the modified query was performed.Test plan
dotnet buildPerformanceMonitor.Collectors— 0 errors, 0 warningsdotnet buildLite.Tests— 0 errors (8 warnings, all pre-existing in unrelated files)devgit hash-object --no-filters+update-index --cacheinfo;--cached --statshows +2 lines, no CRLF renormalization