Introduction SQL Server Extended Events (XEvents) are a lightweight performance monitoring system. However, misconfigured XEvent sessions—especially those capturing high-frequency events, using complex actions, or writing to slow targets—can cause significant CPU overhead and performance degradation on production servers.
Symptoms - CPU usage spikes after enabling an Extended Events session - `sqllang.dll` or `xe.dll` showing high CPU in process monitor - Query performance degrades when XEvent session is active - System Health session causing measurable overhead on busy servers - Ring buffer target filling up and causing memory pressure
Common Causes - Capturing high-frequency events like `sql_statement_completed` on a busy server - Using expensive actions like `sql_text` or `query_plan` on every event - Writing to file target on a slow disk with synchronous writes - No event filtering (predicate) capturing all events instead of specific conditions - Multiple XEvent sessions running simultaneously
Step-by-Step Fix 1. **List active Extended Events sessions": ```sql SELECT s.name AS session_name, s.create_time, s.max_memory, s.total_regular_buffer_size, s.total_buffer_size, s.dropped_event_count, s.create_time FROM sys.dm_xe_sessions s;
-- Check events and actions for each session SELECT s.name AS session_name, e.name AS event_name, a.name AS action_name FROM sys.dm_xe_sessions s JOIN sys.dm_xe_session_events se ON s.address = se.event_session_address JOIN sys.dm_xe_objects e ON se.event_name = e.name LEFT JOIN sys.dm_xe_session_event_actions sea ON se.event_session_address = sea.event_session_address AND se.event_name = sea.event_name LEFT JOIN sys.dm_xe_objects a ON sea.action_name = a.name; ```
- 1.**Stop the problematic session":
- 2.```sql
- 3.ALTER EVENT SESSION [HighCPU_Trace] ON SERVER STATE = STOP;
-- If you need to keep it but reduce impact, modify it ALTER EVENT SESSION [HighCPU_Trace] ON SERVER DROP EVENT sql_statement_completed;
-- Add a more specific event with predicates ALTER EVENT SESSION [HighCPU_Trace] ON SERVER ADD EVENT sqlserver.sql_statement_completed( ACTION(sqlserver.database_name, sqlserver.sql_text) WHERE sqlserver.database_name = 'mydb' AND duration > 1000000 -- Only capture queries over 1 second ); ```
- 1.**Configure the session for lower overhead":
- 2.```sql
- 3.CREATE EVENT SESSION [Optimized_Trace] ON SERVER
- 4.ADD EVENT sqlserver.sql_statement_completed(
- 5.SET collect_statement_text = 0 -- Don't collect text by default
- 6.ACTION(sqlserver.database_id, sqlserver.session_id)
- 7.WHERE sqlserver.database_id > 4 -- Exclude system databases
- 8.AND duration > 500000 -- Microseconds: only slow queries
- 9.)
- 10.ADD TARGET package0.event_file(
- 11.SET filename = N'C:\XEvents\Optimized_Trace.xel',
- 12.max_file_size = 100, -- MB
- 13.max_rollover_files = 4
- 14.)
- 15.WITH (
- 16.MAX_MEMORY = 4096 KB,
- 17.EVENT_RETENTION_MODE = ALLOW_SINGLE_EVENT_LOSS,
- 18.MAX_DISPATCH_LATENCY = 5 SECONDS,
- 19.TRACK_CAUSALITY = OFF
- 20.);
- 21.
` - 22.**Clean up completed session files":
- 23.```sql
- 24.-- Query the event file
- 25.SELECT
- 26.object_name AS event_name,
- 27.CAST(event_data AS XML) AS event_xml,
- 28.file_name
- 29.FROM sys.fn_xe_file_target_read_file(
- 30.'C:\XEvents\Optimized_Trace*.xel',
- 31.NULL, NULL, NULL
- 32.);
- 33.
`