SQL Server Monitoring: Alerts for tempdb Usage and Memory Spills
Objective:
To configure monitoring and alerts in SQL Server for:
1. Queries occupying excessive tempdb space.
2. Orphaned tempdb allocations
3. Memory spills to disk during query execution
1. Alert for Query Occupying Large tempdb Space
Monitoring Query:
SELECT
r.session_id,
r.status,
r.command,
r.start_time,
t.internal_objects_alloc_page_count * 8 / 1024.0 AS InternalMB,
t.user_objects_alloc_page_count * 8 / 1024.0 AS UserMB,
s.login_name,
s.host_name,
s.program_name,
q.text AS SQLText
FROM sys.dm_db_session_space_usage t
JOIN sys.dm_exec_requests r ON t.session_id = r.session_id
JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) q
WHERE (t.internal_objects_alloc_page_count + t.user_objects_alloc_page_count)
* 8 / 1024.0 > 100;
Threshold: 100 MB (customizable)
Recommended Action: Schedule this in a SQL Agent Job and configure email alert if threshold
exceeded.
2. Alert for Orphaned tempdb Allocations
Look for sessions that have no active request but hold TempDB space
Monitoring Query:
SELECT
s.session_id,
s.login_name,
s.host_name,
t.internal_objects_alloc_page_count * 8 / 1024.0 AS InternalMB,
t.user_objects_alloc_page_count * 8 / 1024.0 AS UserMB
FROM sys.dm_db_session_space_usage t
JOIN sys.dm_exec_sessions s ON t.session_id = s.session_id
LEFT JOIN sys.dm_exec_requests r ON s.session_id = r.session_id
WHERE r.session_id IS NULL
AND (t.internal_objects_alloc_page_count + t.user_objects_alloc_page_count)
* 8 / 1024.0 > 50;
Threshold: 50 MB
Recommended Action: Log or alert for cleanup or investigation.
4. Alert for Memory Spills to Disk
Spills to disk usually occur during hashing/sorting and show up in actual execution plans
Setup: Extended Events
CREATE EVENT SESSION [MemorySpillMonitor] ON SERVER
ADD EVENT sqlserver.sort_warning (
ACTION(sqlserver.sql_text, sqlserver.session_id, sqlserver.database_id)
),
ADD EVENT sqlserver.hash_warning (
ACTION(sqlserver.sql_text, sqlserver.session_id, sqlserver.database_id)
)
ADD TARGET package0.ring_buffer
WITH (MAX_MEMORY=4096KB, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
MAX_DISPATCH_LATENCY=30 SECONDS);
ALTER EVENT SESSION [MemorySpillMonitor] ON SERVER STATE = START;
Read Spills:
SELECT
DATEADD(MILLISECOND, event_data.value('(event/@timestamp)[1]', 'bigint')
/ 1000, '1970-01-01') AS [EventTime],
event_data.value('(event/data[@name="sql_text"]/value)[1]',
'nvarchar(max)') AS [SQLText],
event_data.value('(event/action[@name="session_id"]/value)[1]', 'int') AS
[SessionID]
FROM
(
SELECT CAST(target_data AS XML) AS TargetData
FROM sys.dm_xe_sessions s
JOIN sys.dm_xe_session_targets t ON s.address = t.event_session_address
WHERE s.name = 'MemorySpillMonitor'
AND t.target_name = 'ring_buffer'
) AS Data
CROSS APPLY TargetData.nodes('RingBufferTarget/event') AS XTbl(event_data);
Recommended Action: Run daily or integrate with PowerShell to extract and notify.
Implementation Suggestions:
• SQL Agent Job: Automate queries above with threshold checks.
• PowerShell Integration: Optional script to run checks and send alerts.
• Monitoring Tools: Integrate into SQL Sentry, SolarWinds, or custom dashboards.
Purpose: Proactive tempdb and Memory Usage Management