Skip to content

Query statistics misread a cached plan's statistics restart: counters that re-grew are taken as increments (row-coherent reset needed) #4428

Description

@erikdarlingdata

Claude posting for Erik Darling

Problem

When SQL Server resets a cached plan's statistics and the plan comes back under the same key, the query-stats collector misreads the restart. Counters that re-grew past their old values are taken as ordinary increments, and counters that didn't re-grow are taken as reset. So one row gets a mix of under-counted deltas and a "no delta knowable" CPU with a zero interval.

  • Where: PerformanceMonitor.Collectors/QueryStatsCollector.cs (shared by Darling and Lite). It makes one CalculateDeltaWithSeriesAge call per counter family, each with its own cache, for the same key (sql_handle:start:end:plan_handle). CollectorDeltaCalculator.Core decides the reset path per family.
  • Field evidence (read-only, 24 h, two production SQL Server stores): every query_stats row with a zero interval but a nonzero execution or elapsed delta followed a DROP in total_worker_time for the same key. 188 of 188 on one store and 8,807 of 8,807 on the other; no first sightings, and no rows without a drop.
    • In most, the execution count had re-grown past its old value. For example, execution count 1 → 16 while total_worker_time went 57,695,259 → 703,943 µs. The collector stored an execution delta of 15 (the true work since the restart is 16), and CPU as unknown with a zero interval.
  • Effect:

Fix

Related

#4394 (where this was found), #4423, #2235, #2234.

Activity

  1. erikdarlingdata commented on Sep 26, 2026

    @erikdarlingdata
    OwnerAuthor

    Claude posting for Erik Darling.

    #4431 is merged (ef7e75d). query_stats now decides a restarted cached plan's counters for the whole row at once. A restart inside the gap records the current values over the real interval, and a restart the collector cannot place records the row as unknown. wait_stats and pg_statement_stats are not changed yet, so this issue stays open for them.

  2. erikdarlingdata commented on Sep 26, 2026

    @erikdarlingdata
    OwnerAuthor

    Claude posting for Erik Darling.

    #4434 is merged (77fce3a). The wait_stats collector detects a server-wide wait-stats clear: at least half of at least 20 baselined types read lower, and the total dropped. The figures after a clear then count from it, instead of being recorded as unknown. pg_statement_stats (#4435) is the last part, so this issue stays open until it merges.

  3. erikdarlingdata commented on Sep 26, 2026

    @erikdarlingdata
    OwnerAuthor

    Claude posting for Erik Darling.

    All three parts are merged, so this issue is closing:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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