WAIT_ON_SYNC_STATISTICS_REFRESH is recorded when a query has to wait for a synchronous statistics update to finish before it can compile and run. With auto-update statistics in its default synchronous mode, a query that trips the staleness threshold on a table’s statistics stops, updates those statistics right there, and only then compiles. This wait, added so that time is finally visible, measures the stall.
It is the named version of an old mystery: “the same query is instant normally but took 40 seconds once, then was instant again.”
Is It a Problem?
It is when it registers meaningfully, because real user queries are absorbing statistics maintenance time at random. How bad depends on the tables: the refresh cost scales with row counts, the number of statistics involved, and options like FULLSCAN. On large, volatile tables (ETL staging, big fact tables) a synchronous refresh mid-workload can stall a query for a long time, and everything queuing behind it feels it too.
Occasional small blips on modest tables are the system working as designed.
Common Causes
- Auto-update statistics running synchronously (the default) on large tables that churn past the modification threshold during busy hours.
- ETL loads modifying enough rows to invalidate statistics, with the next unlucky user query paying the refresh bill.
- Many statistics objects on one table each needing a refresh in the same compile.
What To Do
- Turn on asynchronous statistics updates for the affected databases:
ALTER DATABASE [db] SET AUTO_UPDATE_STATISTICS_ASYNC ON;. Queries then compile with the stale statistics while the refresh happens in the background, trading momentary staleness for no stalls. For most OLTP workloads that trade is clearly right. - Get ahead of auto-update by maintaining statistics yourself: scheduled
UPDATE STATISTICSon the known churners after their load windows (our statistics health script shows which are stale). - On SQL Server 2019 and later, remember the sampling improvements and persisted sample rates when tuning how expensive each refresh is.
How To See It
Rank it against everything else with Get-WaitStatistics, and correlate spikes with your data load schedule; the pattern is usually obvious within a day of watching.
Part of the SQL Server Wait Types Library.
Related deep dive: RESOURCE_SEMAPHORE Wait Type.
Leave a Reply