SQL Server Tuning
SQL Server Tuning
Performance Tuning
Asfaw Gedamu
SQL Server Scripts for Performance Tuning
Are sluggish queries, deadlocks, or mysterious CPU spikes keeping you up at night?
Performance tuning is like detective work. Without the right tools, you’re stuck chasing ghosts.
This 20-script guide cuts through the noise. From pinpointing long-running queries to crushing
index fragmentation and slashing deadlocks, these scripts are your Swiss Army knife for SQL
Server performance. No fluff, no theory, just actionable code to transform chaos into clarity.
Always test scripts in non-production environments first!
SELECT
TOP 10 SUBSTRING(qt.TEXT, (qs.statement_start_offset/2) + 1,
((CASE statement_end_offset
WHEN -1 THEN DATALENGTH(qt.TEXT)
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2) + 1),
qs.execution_count,
qs.total_logical_reads, qs.last_logical_reads,
qs.total_logical_writes, qs.last_logical_writes,
qs.total_worker_time,
qs.last_worker_time,
qs.total_elapsed_time/1000000 total_elapsed_time_in_sec,
qs.last_elapsed_time/1000000 last_elapsed_time_in_sec,
qs.last_execution_time,
qp.query_plan
FROM
sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY qs.total_logical_reads DESC -- logical reads
-- ORDER BY qs.total_logical_writes DESC -- logical writes
-- ORDER BY qs.total_worker_time DESC -- CPU time
1. How to check index fragmentation
SELECT
dbschemas.[name] as 'Schema',
dbtables.[name] as 'Table',
dbindexes.[name] as 'Index',
indexstats.avg_fragmentation_in_percent,
indexstats.page_count
FROM
sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL,
NULL) AS indexstats
INNER JOIN sys.tables dbtables on dbtables.[object_id] =
indexstats.[object_id]
INNER JOIN sys.schemas dbschemas on dbtables.[schema_id] =
dbschemas.[schema_id]
INNER JOIN sys.indexes AS dbindexes ON dbindexes.[object_id]
= indexstats.[object_id]
AND indexstats.index_id = dbindexes.index_id
WHERE
indexstats.database_id = DB_ID()
ORDER BY
indexstats.avg_fragmentation_in_percent DESC
SELECT
blocking_session_id AS BlockingSessionID,
session_id AS VictimSessionID,
(SELECT text FROM sys.dm_exec_sql_text(sql_handle)) AS
SQLQuery
FROM sys.dm_exec_requests
WHERE blocking_session_id > 0
SELECT
dm_mid.database_id,
dm_mid.[object_id],
dm_migs.avg_total_user_cost * (dm_migs.avg_user_impact /
100.0) * (dm_migs.user_seeks + dm_migs.user_scans) AS
improvement_measure,
'CREATE INDEX missing_index_' + CONVERT (varchar,
dm_mid.index_group_handle) + '_' + CONVERT (varchar,
dm_mid.index_handle) + ' ON ' + dm_mid.statement + ' (' + ISNULL
(dm_mic.column_store, '') + ')' + ISNULL
(dm_mic.equality_columns,'')
+ CASE WHEN dm_mic.equality_columns IS NOT NULL AND
dm_mic.inequality_columns IS NOT NULL THEN ',' ELSE '' END +
ISNULL (dm_mic.inequality_columns, '') + ')' + ISNULL (' INCLUDE
(' + dm_mic.included_columns + ')', '') AS
create_index_statement,
dm_migs.*,
dm_mid.database_id,
dm_mid.[object_id]
FROM
sys.dm_db_missing_index_groups dm_mig
INNER JOIN sys.dm_db_missing_index_group_stats dm_migs ON
dm_migs.group_handle = dm_mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details dm_mid ON
dm_mig.index_handle = dm_mid.index_handle
INNER JOIN (
SELECT
index_handle,
STRING_AGG(column_name, ', ') WITHIN GROUP (ORDER BY
column_name) AS column_store
FROM sys.dm_db_missing_index_columns (NULL)
WHERE column_usage = 'STORE'
GROUP BY index_handle
) AS dm_mic_store ON dm_mid.index_handle =
dm_mic_store.index_handle
LEFT JOIN (
SELECT
index_handle,
STRING_AGG(column_name, ', ') WITHIN GROUP (ORDER BY
column_name) AS equality_columns,
STRING_AGG(column_name, ', ') WITHIN GROUP (ORDER BY
column_name) AS inequality_columns,
STRING_AGG(column_name, ', ') WITHIN GROUP (ORDER BY
column_name) AS included_columns
FROM sys.dm_db_missing_index_columns (NULL)
WHERE column_usage = 'EQUALITY' OR column_usage =
'INEQUALITY' OR column_usage = 'INCLUDE'
GROUP BY index_handle
) AS dm_mic ON dm_mid.index_handle = dm_mic.index_handle
WHERE
dm_mid.database_id = DB_ID()
ORDER BY
improvement_measure DESC
SELECT
SQLProcessUtilization AS [SQL Server Process CPU
Utilization],
SystemIdle AS [System Idle Process],
100 - SystemIdle - SQLProcessUtilization AS [Other Process
CPU Utilization]
FROM
(SELECT
record_id,
dateadd(ms, -1 * ((sys.ms_ticks / 1000) - [timestamp]),
GetDate()) as [Event Time],
SQLProcessUtilization,
SystemIdle
FROM
(SELECT
record_id,
sys.ms_ticks,
[timestamp],
convert(xml, record) as [record]
FROM sys.dm_os_ring_buffers
CROSS JOIN sys.dm_os_sys_info sys
WHERE ring_buffer_id = 1
AND record_id > (SELECT MAX(record_id) FROM
sys.dm_os_ring_buffers WHERE ring_buffer_id = 1) - 60
) AS x
) AS y
ORDER BY record_id DESC;
SELECT
[object_name],
counter_name,
cntr_value
FROM
sys.dm_os_performance_counters
WHERE
[object_name] LIKE '%Manager%'
AND counter_name = 'Page life expectancy'
SELECT
TOP 5 total_logical_reads,
total_logical_writes,
total_physical_reads, total_physical_reads,
execution_count,
total_logical_reads + total_logical_writes AS [Aggregated
I/O],
total_elapsed_time,
statement_start_offset,
statement_end_offset,
plan_handle,
sql_handle
FROM
sys.dm_exec_requests
ORDER BY
[Aggregated I/O] DESC;
SELECT
XEvent.query('(data/value/deadlock)[1]') AS DeadlockGraph
FROM
(SELECT
XEvent.query('.') AS XEvent
FROM
(SELECT
CAST(target_data AS XML) AS TargetData
FROM
sys.dm_xe_session_targets st
JOIN
sys.dm_xe_sessions s ON s.address =
st.event_session_address
WHERE
name = 'system_health') AS Data
CROSS APPLY
TargetData.nodes ('//RingBufferTarget/event') AS
XEventData (XEvent)
) AS src
WHERE
XEvent.value('(@name)[1]', 'varchar(4000)') =
'xml_deadlock_report';
SELECT
blocked_session_id,
blocking_session_id,
wait_type,
wait_duration_ms,
resource_description,
(SELECT text FROM sys.dm_exec_sql_text(sql_handle)) AS
sql_text
FROM
sys.dm_os_waiting_tasks
WHERE
blocking_session_id IS NOT NULL;
OPEN IndexCursor
FETCH NEXT FROM IndexCursor INTO @SchemaName, @TableName,
@IndexName, @FragPercent
WHILE @@FETCH_STATUS = 0
BEGIN
IF @FragPercent > 30
BEGIN
EXEC('ALTER INDEX [' + @IndexName + '] ON [' +
@SchemaName + '].[' + @TableName + '] REBUILD')
END
ELSE
BEGIN
EXEC('ALTER INDEX [' + @IndexName + '] ON[' +
@SchemaName + '].[' + @TableName + '] REORGANIZE')
END
CLOSE IndexCursor
DEALLOCATE IndexCursor
Unlock peak efficiency with these 20 expert-level scripts, designed to expose hidden
issues, optimize resources, and keep your database running like a well-oiled machine.
https://t.me/paragonacademy