Skip to content

[FEATURE] Auto force plan bot — detect bad Query Store plans (CPU-weighted), force with self-review, evict-first option #2138

Description

@erikdarlingdata

From Erik's feature email ('Auto force plan bot', 2026-08-08/09). Faithful decomposition of the ask, then a proposed phasing.

The ask, verbatim requirements

  1. Detection: find opportunities to force Query Store plans when a bad plan is detected. Signal = CPU + duration combined, CPU weighted stronger (duration is confounded by factors outside the plan).
  2. Importance gate: prerequisites before acting — significant executions AND resource expenditure judge whether a query matters enough.
  3. Self-review + regression ledger: post-force review phases, and tracking for plan forces that were not a net benefit.
  4. Live-activity component: watch server activity for queries currently running hot; target them with DBCC FREEPROCCACHE (targeted, per-plan) so a newly forced plan takes effect immediately.
  5. Evict-first strategy: optionally clear the bad plan FIRST and observe whether the optimizer picks a better plan before resorting to forcing.
  6. Goal: parameter-sensitive plans, and queries adversely affected by a stats update.

What already exists to build on

  • query_store_stats series: per-plan CPU/duration/executions over time, both SKUs — the detection substrate is already collected.
  • PlanCorrectionCollector: sys.dm_db_tuning_recommendations + FORCE_LAST_GOOD_PLAN desired/actual state — the engine's own regression opinions, already shredded and stored.
  • remediation_action_json precedent: findings that carry executable T-SQL.
  • Active-query snapshots for the currently-hot component.
  • House rule to honor: the bot's self-review may only unforce its own forces — operator-placed forces are never touched.

Proposed phasing (the write-access question is the product decision)

  • Phase 0 — advise-only detection (no target writes; shippable alone): plan-regression scoring from the stored QS series — per (query, plan) compare candidate vs incumbent on CPU-weighted deltas, gated by executions × resource spend; classify parameter-sensitivity (plan alternation) vs stats-update regression (correlate with stats timestamps); surface as findings with the exact sp_query_store_force_plan / DBCC FREEPROCCACHE(plan_handle) remediation attached.
  • Phase 1 — evict-first, operator-armed: one-click/one-call execution of the targeted eviction with before/after observation windows, still human-initiated.
  • Phase 2 — the bot: opt-in per server; evict-first then force-if-still-bad; post-force self-review windows; auto-unforce + not-a-net-benefit ledger; cooldowns and blast-radius caps (max actions/window); full audit trail. Requires a write-capable credential tier the product currently doesn't ask operators for — deliberate opt-in surface.

Phase 0 is unambiguous and read-only; starting there. Phases 1–2 want a design pass (credentials, gating UX, review-window arithmetic) before code.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions