T The Triage ManualTechnical Guides for IT Emergencies
P3 · Windows Server

Identifying SQL Statements Causing TempDB Growth in SQL Server

TempDB can grow to hundreds of gigabytes due to complex queries involving sort spills, hash joins, or large intermediate result sets — not always from explicit temporary table creation. Three DMVs (sys.dm_db_task_space_usage, sys.dm_db_session_space_usage, sys.dm_db_file_space_usage) can pinpoint allocations at the task, session, and file level respectively. Offending queries can be identified in real time via sys.dm_exec_sql_text, or historically via scheduled sp_whoisactive collection, then remediated through query optimisation, index tuning, and plan cache management.

Indicators

Likely causes

Diagnostic steps

  1. Query sys.dm_db_file_space_usage to get a current aggregate breakdown of TempDB space by version store, user objects, and internal objects: SELECT SUM(version_store_reserved_page_count)*8 AS [Version Store KB], SUM(user_object_reserved_page_count)*8 AS [User Objects KB], SUM(internal_object_reserved_page_count)*8 AS [Internal Objects KB], SUM(unallocated_extent_page_count)*8 AS [Free KB] FROM sys.dm_db_file_space_usage — this establishes which category of usage is dominant.
  2. Query sys.dm_db_session_space_usage joined with sys.dm_exec_sessions to identify which sessions are consuming the most TempDB space: SELECT s.session_id, DB_NAME(s.database_id) AS db_name, s.host_name, s.program_name, s.login_name, s.status, (u.user_objects_alloc_page_count * 8) AS [User Objects KB], (u.internal_objects_alloc_page_count * 8) AS [Internal Objects KB] FROM sys.dm_db_session_space_usage u INNER JOIN sys.dm_exec_sessions s ON u.session_id = s.session_id ORDER BY (u.user_objects_alloc_page_count + u.internal_objects_alloc_page_count) DESC
  3. For currently executing requests, query sys.dm_db_task_space_usage joined with sys.dm_exec_requests and sys.dm_exec_sql_text to get task-level TempDB allocation alongside the SQL statement: SELECT t.session_id, t.request_id, (t.internal_objects_alloc_page_count * 8) AS [Internal KB], (t.user_objects_alloc_page_count * 8) AS [User KB], SUBSTRING(st.text, (r.statement_start_offset/2)+1, ((CASE r.statement_end_offset WHEN -1 THEN DATALENGTH(st.text) ELSE r.statement_end_offset END - r.statement_start_offset)/2)+1) AS statement_text FROM sys.dm_db_task_space_usage t INNER JOIN sys.dm_exec_requests r ON t.session_id = r.session_id AND t.request_id = r.request_id CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) st ORDER BY (t.internal_objects_alloc_page_count + t.user_objects_alloc_page_count) DESC
  4. For sessions identified in step 2 that are no longer actively executing (idle sessions holding space), retrieve the last executed SQL using sys.dm_exec_connections joined with sys.dm_exec_sql_text on the most_recent_sql_handle column.
  5. Deploy sp_whoisactive (Adam Machanic) via a SQL Agent job running every 1–5 minutes, logging output to a dedicated table. This enables post-incident analysis to identify which queries were executing during growth events: EXEC sp_whoisactive @output_column_list = '[dd%][session_id][sql_text][login_name][wait_info][tasks][tran_log%][cpu%][temp%][block%][reads%][writes%][context%][physical_io%][query_plan][locks%][%]', @destination_table = 'dbo.WhoIsActiveLog'
  6. Review execution plans of the identified offending queries in SSMS (actual execution plan) and look for Sort and Hash Match operators with a Warnings icon indicating spill to TempDB. These are the primary internal object consumers.
  7. If TempDB cannot be shrunk, identify cached plans holding locks: run DBCC FREEPROCCACHE to clear the plan cache (schedule during low-traffic window), then retry DBCC SHRINKFILE against each TempDB data file. Confirm no active sessions remain on TempDB beforehand.
  8. Check TempDB file configuration: verify the number of data files (target: one per logical CPU core up to 8, all equal size), confirm autogrowth is set to a fixed MB value rather than percentage, and confirm initial sizes are set to a reasonable pre-allocated value to prevent repeated auto-growth events.

Resolution path

Prevention

Tools

References

sql-serversql-server-2008tempdbperformancedmvdisk-spacequery-optimizationsort-spillhash-joinmonitoringsp-whoisactiveplan-cacheinternal-objectsversion-store