Less Data, 180x Slower: A SQL Server Mystery
Nov 15, 2025
A few months back I optimized an extremely complex sales report query. It was running clean in production, consistently fast.
Last week it suddenly took over a minute to run.
- No deploys.
- No schema changes.
- Same hardware.
- Same query.
The Weird Discovery
So I started testing different date ranges and found something weird:
- Sep 10 → Nov 15 (67 days): less than half a second
- Sep 11 → Nov 15 (66 days): 90 seconds 😭
Removing one day made the query 180× slower. That should not be possible.
What I Checked
- Indexes? ✔ same for both ranges
- Data anomaly on Sep 11? ✔ normal day (~100 invoices)
- Locks? ✔ tested off-peak
- Hardware? ✔ unchanged
Nothing explained it.
The Real Culprit: Stale Statistics
SQL Server’s optimizer relies on statistics to estimate row counts and pick join strategies & execution plans. In my case, those were outdated… and one date range fell into a histogram step that was completely mis-estimated.
Here’s what actually happened:
For the Sep 10 start date:
Old stats happened to estimate the row count reasonably. SQL Server picked a good plan: index seeks + hash joins + parallelism.
Result: < 0.5s
For the Sep 11 start date: Same stale stats drastically underestimated the row count. Optimizer picked a plan meant for tiny datasets: nested loops, no parallelism. Real volume crushed it → 90 seconds.
Same table. Same query. Completely different plan because the stats were lying.
The Fix
UPDATE STATISTICS table_name; Back to sub-second instantly.
Why It Happened
SQL Server auto-updates stats when ~20% of rows change, but:
- Bulk operations
- Skewed data patterns
- Ascending keys
…can all prevent auto-update from triggering. The stats slowly became inaccurate over time, and my months-old optimization was based on fresh stats that had since decayed.
Prevention (Add to maintenance)
UPDATE STATISTICS table_name WITH FULLSCAN; A query that runs perfectly today can fail next month because the optimizer’s mental model of your data is outdated.