0% found this document useful (0 votes)
12 views

sqlserver 脚本

The document provides a comprehensive overview of various SQL Server dynamic management views (DMVs) and queries used for performance monitoring and troubleshooting. It includes instructions for gathering wait statistics, virtual file statistics, query execution statistics, and identifying missing indexes, among other performance metrics. Additionally, it outlines methods for analyzing session waits, CPU consumption, and the impact of locks on performance.

Uploaded by

jun peng
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
12 views

sqlserver 脚本

The document provides a comprehensive overview of various SQL Server dynamic management views (DMVs) and queries used for performance monitoring and troubleshooting. It includes instructions for gathering wait statistics, virtual file statistics, query execution statistics, and identifying missing indexes, among other performance metrics. Additionally, it outlines methods for analyzing session waits, CPU consumption, and the impact of locks on performance.

Uploaded by

jun peng
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 29

1、系统等待统计信息

sys.dm_os_wait_stats
2、虚拟文件统计信息
sys.dm_io_virtual_file_stats
3、查询执行统计信息
sys.dm_exec_query_stats
3.1、查找正在运行的批处理的查询文本
sys.dm_exec_requests
SELECT * FROM sys.dm_exec_sql_text(< copied sql_handle >);
3.2、查找锁信息
SELECT * FROM sys.dm_tran_locks WHERE request_owner_type = N'TRANSACTION' AND
request_owner_id = < copied transaction_id >;
3.3、查找有关被阻塞的请求的信息
SELECT
session_id ,status ,blocking_session_id,wait_type ,wait_time ,wait_resource ,transa
ction_id FROM sys.dm_exec_requests WHERE status = N'suspended';
4、系统会话等待
SELECT DISTINCT
wt.wait_type
FROM
sys.dm_os_waiting_tasks AS wt
JOIN sys.dm_exec_sessions AS s ON wt.session_id = s.session_id
WHERE s.is_user_process = 0
5、查找前 10 个累积等待事件
SELECT TOP 10
wait_type ,
max_wait_time_ms wait_time_ms ,
signal_wait_time_ms ,
wait_time_ms - signal_wait_time_ms AS resource_wait_time_ms ,
100.0 * wait_time_ms / SUM(wait_time_ms) OVER ( )
AS percent_total_waits ,
100.0 * signal_wait_time_ms / SUM(signal_wait_time_ms) OVER ( )
AS percent_total_signal_waits ,
100.0 * ( wait_time_ms - signal_wait_time_ms )
/ SUM(wait_time_ms) OVER ( ) AS percent_total_resource_waits
FROM sys.dm_os_wait_stats
WHERE wait_time_ms > 0 -- remove zero wait_time
AND wait_type NOT IN -- filter out additional irrelevant waits
( 'SLEEP_TASK', 'BROKER_TASK_STOP', 'BROKER_TO_FLUSH',
'SQLTRACE_BUFFER_FLUSH','CLR_AUTO_EVENT', 'CLR_MANUAL_EVENT',
'LAZYWRITER_SLEEP', 'SLEEP_SYSTEMTASK', 'SLEEP_BPOOL_FLUSH',
'BROKER_EVENTHANDLER', 'XE_DISPATCHER_WAIT', 'FT_IFTSHC_MUTEX',
'CHECKPOINT_QUEUE', 'FT_IFTS_SCHEDULER_IDLE_WAIT',
'BROKER_TRANSMITTER', 'FT_IFTSHC_MUTEX', 'KSOURCE_WAKEUP',
'LOGMGR_QUEUE', 'ONDEMAND_TASK_QUEUE',
'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT', 'BAD_PAGE_PROCESS',
'DBMIRROR_EVENTS_QUEUE', 'BROKER_RECEIVE_WAITFOR',
'PREEMPTIVE_OS_GETPROCADDRESS', 'PREEMPTIVE_OS_AUTHENTICATIONOPS',
'WAITFOR', 'DISPATCHER_QUEUE_SEMAPHORE', 'XE_DISPATCHER_JOIN',
'RESOURCE_QUEUE' )
ORDER BY wait_time_ms DESC
#
CXPACKET:并行等待
SOS_SCHEDULER_YIELD:SOS 调度器 现象:可能表示服务器面临 CPU 压力
THREADPOOL:线程池 现象:需要增加服务器中的 CPU 数量
LCK_*:锁 现象:表示系统中正在发生阻塞,sys.dm_db_index_operational_stats

PAGEIOLATCH_*, IO_COMPLETION, WRITELOG:通常与磁盘 I/O 瓶颈有关


PAGELATCH_*:等待缓冲池中数据页上的闩锁,希望将下一个焦点设为虚拟文件统计信息
LATCH_*:这些对象用于保护对内部高速缓存的访问,而不是缓冲区高速缓存,sys.dm_os_latch_stats
ASYNC_NETWORK_IO:这种等待通常被错误地归因于网络瓶颈

6、重置服务器跟踪的等待统计信息
DBCC SQLPERF('sys.dm_os_wait_stats', clear)
7、虚拟文件统计信息(数据文件,日志文件 IO)
SELECT DB_NAME(vfs.database_id) AS database_name ,
vfs.database_id ,
vfs.FILE_ID ,
io_stall_read_ms / NULLIF(num_of_reads, 0) AS avg_read_latency ,
io_stall_write_ms / NULLIF(num_of_writes, 0)
AS avg_write_latency ,
io_stall / NULLIF(num_of_reads + num_of_writes, 0)
AS avg_total_latency ,
num_of_bytes_read / NULLIF(num_of_reads, 0)
AS avg_bytes_per_read ,
num_of_bytes_written / NULLIF(num_of_writes, 0)
AS avg_bytes_per_write ,
vfs.io_stall ,
vfs.num_of_reads ,
vfs.num_of_bytes_read ,
vfs.io_stall_read_ms ,
vfs.num_of_writes ,
vfs.num_of_bytes_written ,
vfs.io_stall_write_ms ,
size_on_disk_bytes / 1024 / 1024. AS size_on_disk_mbytes ,
physical_name
FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS vfs
JOIN sys.master_files AS mf ON vfs.database_id = mf.database_id
AND vfs.FILE_ID = mf.FILE_ID
ORDER BY avg_total_latency DESC
8、性能计数器
sys.dm_os_perfor mance_counters
DECLARE @CounterPrefix NVARCHAR(30)
SET @CounterPrefix = CASE WHEN @@SERVICENAME = 'MSSQLSERVER'
THEN 'SQLServer:'
ELSE 'MSSQL$' + @@SERVICENAME + ':'
END ; -- Capture the first counter set
SELECT CAST(1 AS INT) AS collection_instance ,
[OBJECT_NAME] ,
counter_name ,
instance_name ,
cntr_value ,
cntr_type ,
CURRENT_TIMESTAMP AS collection_time
INTO #perf_counters_init
FROM sys.dm_os_performance_counters
WHERE ( OBJECT_NAME = @CounterPrefix + 'Access Methods'
AND counter_name = 'Full Scans/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Access Methods'
AND counter_name = 'Index Searches/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Buffer Manager'
AND counter_name = 'Lazy Writes/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Buffer Manager'
AND counter_name = 'Page life expectancy'
)
OR ( OBJECT_NAME = @CounterPrefix + 'General Statistics'
AND counter_name = 'Processes Blocked'
)
OR ( OBJECT_NAME = @CounterPrefix + 'General Statistics'
AND counter_name = 'User Connections'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Locks'
AND counter_name = 'Lock Waits/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Locks'
AND counter_name = 'Lock Wait Time (ms)'
)
OR ( OBJECT_NAME = @CounterPrefix + 'SQL Statistics'
AND counter_name = 'SQL Re-Compilations/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Memory Manager'
AND counter_name = 'Memory Grants Pending'
)
OR ( OBJECT_NAME = @CounterPrefix + 'SQL Statistics'
AND counter_name = 'Batch Requests/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'SQL Statistics'
AND counter_name = 'SQL Compilations/sec'
)
-- Wait on Second between data collection
WAITFOR DELAY '00:00:01'
-- Capture the second counter set
SELECT CAST(2 AS INT) AS collection_instance ,
OBJECT_NAME ,
counter_name ,
instance_name ,
cntr_value ,
cntr_type ,
CURRENT_TIMESTAMP AS collection_time
INTO #perf_counters_second
FROM sys.dm_os_performance_counters
WHERE ( OBJECT_NAME = @CounterPrefix + 'Access Methods'
AND counter_name = 'Full Scans/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Access Methods'
AND counter_name = 'Index Searches/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Buffer Manager'
AND counter_name = 'Lazy Writes/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Buffer Manager'
AND counter_name = 'Page life expectancy'
)
OR ( OBJECT_NAME = @CounterPrefix + 'General Statistics'
AND counter_name = 'Processes Blocked'
)
OR ( OBJECT_NAME = @CounterPrefix + 'General Statistics'
AND counter_name = 'User Connections'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Locks'
AND counter_name = 'Lock Waits/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Locks'
AND counter_name = 'Lock Wait Time (ms)'
)
OR ( OBJECT_NAME = @CounterPrefix + 'SQL Statistics'
AND counter_name = 'SQL Re-Compilations/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'Memory Manager'
AND counter_name = 'Memory Grants Pending'
)
OR ( OBJECT_NAME = @CounterPrefix + 'SQL Statistics'
AND counter_name = 'Batch Requests/sec'
)
OR ( OBJECT_NAME = @CounterPrefix + 'SQL Statistics'
AND counter_name = 'SQL Compilations/sec'
)
-- Calculate the cumulative counter values
SELECT i.OBJECT_NAME ,
i.counter_name ,
i.instance_name ,
CASE WHEN i.cntr_type = 272696576
THEN s.cntr_value - i.cntr_value
WHEN i.cntr_type = 65792 THEN s.cntr_value
END AS cntr_value
FROM #perf_counters_init AS i
JOIN #perf_counters_second AS s
ON i.collection_instance + 1 = s.collection_instance
AND i.OBJECT_NAME = s.OBJECT_NAME
AND i.counter_name = s.counter_name
AND i.instance_name = s.instance_name
ORDER BY OBJECT_NAME
-- Cleanup tables
DROP TABLE #perf_counters_init
DROP TABLE #perf_counters_second
9、根据语句在执行过程中执行的平均物理读取次数列出前 10 个语句
SELECT TOP 10
execution_count ,
statement_start_offset AS stmt_start_offset ,
sql_handle , plan_handle ,
total_logical_reads / execution_count AS avg_logical_reads ,
total_logical_writes / execution_count AS avg_logical_writes ,
total_physical_reads / execution_count AS avg_physical_reads ,
t.text
FROM
sys.dm_exec_query_stats AS s
-- CROSS APPLY sys.dm_exec_query_plan(s.plan_handles) AS t
CROSS APPLY sys.dm_exec_sql_text(s.sql_handle) AS t
ORDER BY avg_physical_reads DESC
10、查找 CPU 消耗量排名前 10 的查询
SELECT TOP ( 10 )
SUBSTRING(ST.text, ( QS.statement_start_offset / 2 ) + 1,
( ( CASE statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE QS.statement_end_offset
END - QS.statement_start_offset ) / 2 ) + 1)
AS statement_text , execution_count ,
total_worker_time / 1000 AS total_worker_time_ms ,
( total_worker_time / 1000 ) / execution_count
AS avg_worker_time_ms ,
total_logical_reads ,
total_logical_reads / execution_count AS avg_logical_reads ,
total_elapsed_time / 1000 AS total_elapsed_time_ms ,
( total_elapsed_time / 1000 ) / execution_count
AS avg_elapsed_time_ms ,
qp.query_plan
FROM
sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY total_worker_time DESC

11、根据查询成本优势识别缺失索引
SELECT migs.avg_total_user_cost * ( migs.avg_user_impact / 100.0 )
* ( migs.user_seeks + migs.user_scans ) AS improvement_measure ,
'CREATE INDEX [missing_index_'
+ CONVERT (VARCHAR, mig.index_group_handle) + '_'
+ CONVERT (VARCHAR, mid.index_handle) + '_'
+ LEFT(PARSENAME(mid.statement, 1), 32) + ']' + ' ON '
+ mid.statement
+ ' (' + ISNULL(mid.equality_columns, '')
+ CASE WHEN mid.equality_columns IS NOT NULL
AND mid.inequality_columns IS NOT NULL THEN ','
ELSE ''
END + ISNULL(mid.inequality_columns, '') + ')'
+ ISNULL(' INCLUDE ('
+ mid.included_columns
+ ')', '')
AS create_index_statement ,
migs.* ,
mid.database_id ,
mid.[object_id]
FROM sys.dm_db_missing_index_groups mig
INNER JOIN sys.dm_db_missing_index_group_stats migs
ON migs.group_handle = mig.index_group_handle
INNER JOIN sys.dm_db_missing_index_details mid
ON mig.index_handle = mid.index_handle
WHERE migs.avg_total_user_cost * ( migs.avg_user_impact / 100.0 )
* ( migs.user_seeks + migs.user_scans ) > 10
ORDER BY migs.avg_total_user_cost * migs.avg_user_impact
* ( migs.user_seeks + migs.user_scans ) DESC
12、从 XML 显示计划中解析缺失的索引信息。
WITH XMLNAMESPACES
(DEFAULT 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
SELECT MissingIndexNode.value('(MissingIndexGroup/@Impact)[1]', 'float')
AS impact ,
OBJECT_NAME(sub.objectid, sub.dbid) AS calling_object_name ,
MissingIndexNode.value
('(MissingIndexGroup/MissingIndex/@Database)[1]',
'VARCHAR(128)') + '.'
+ MissingIndexNode.value
('(MissingIndexGroup/MissingIndex/@Schema)[1]',
'VARCHAR(128)') + '.'
+ MissingIndexNode.value
('(MissingIndexGroup/MissingIndex/@Table)[1]',
'VARCHAR(128)') AS table_name ,
STUFF(( SELECT ',' + c.value('(@Name)[1]', 'VARCHAR(128)')
FROM MissingIndexNode.nodes
('MissingIndexGroup/MissingIndex/
ColumnGroup[@Usage="EQUALITY"]/Column')
AS t ( c )
FOR
XML PATH('')
), 1, 1, '') AS equality_columns ,
STUFF(( SELECT ',' + c.value('(@Name)[1]', 'VARCHAR(128)')
FROM MissingIndexNode.nodes
('MissingIndexGroup/MissingIndex/
ColumnGroup[@Usage="INEQUALITY"]/Column')
AS t ( c )
FOR
XML PATH('')
), 1, 1, '') AS inequality_columns ,
STUFF(( SELECT ',' + c.value('(@Name)[1]', 'VARCHAR(128)')
FROM MissingIndexNode.nodes
('MissingIndexGroup/MissingIndex/
ColumnGroup[@Usage="INCLUDE"]/Column')
AS t ( c )
FOR
XML PATH('')
), 1, 1, '') AS include_columns ,
sub.usecounts AS qp_usecounts ,
sub.refcounts AS qp_refcounts ,
qs.execution_count AS qs_execution_count ,
qs.last_execution_time AS qs_last_exec_time ,
qs.total_logical_reads AS qs_total_logical_reads ,
qs.total_elapsed_time AS qs_total_elapsed_time ,
qs.total_physical_reads AS qs_total_physical_reads ,
qs.total_worker_time AS qs_total_worker_time ,
StmtPlanStub.value('(StmtSimple/@StatementText)[1]', 'varchar(8000)') AS
statement_text
FROM ( SELECT ROW_NUMBER() OVER
( PARTITION BY qs.plan_handle
ORDER BY qs.statement_start_offset )
AS StatementID ,
qs.*
FROM sys.dm_exec_query_stats qs
) AS qs
JOIN ( SELECT x.query('../../..') AS StmtPlanStub ,
x.query('.') AS MissingIndexNode ,
x.value('(../../../@StatementId)[1]', 'int')
AS StatementID ,
cp.* ,
qp.*
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_query_plan
(cp.plan_handle) qp
CROSS APPLY qp.query_plan.nodes
('/ShowPlanXML/BatchSequence/
Batch/Statements/StmtSimple/
QueryPlan/MissingIndexes/
MissingIndexGroup') mi ( x )
) AS sub ON qs.plan_handle = sub.plan_handle
AND qs.StatementID = sub.StatementID
13、标识单列、非索引的 FOREIGN KEY。
SELECT fk.name AS CONSTRAINT_NAME ,
s.name AS SCHEMA_NAME ,
o.name AS TABLE_NAME ,
fkc_c.name AS CONSTRAINT_COLUMN_NAME
FROM
sys.foreign_keys AS fk
JOIN sys.foreign_key_columns AS fkc
ON fk.object_id = fkc.constraint_object_id
JOIN sys.columns AS fkc_c
ON fkc.parent_object_id = fkc_c.object_id
AND fkc.parent_column_id = fkc_c.column_id
LEFT JOIN sys.index_columns ic
JOIN sys.columns AS c ON ic.object_id = c.object_id
AND ic.column_id = c.column_id
ON fkc.parent_object_id = ic.object_id
AND fkc.parent_column_id = ic.column_id
JOIN sys.objects AS o ON o.object_id = fk.parent_object_id
JOIN sys.schemas AS s ON o.schema_id = s.schema_id
WHERE c.name IS NULL
14、查找未使用的非聚集索引
SELECT OBJECT_SCHEMA_NAME(i.object_id) AS SchemaName ,
OBJECT_NAME(i.object_id) AS TableName ,
i.name ,
ius.user_seeks ,
ius.user_scans ,
ius.user_lookups ,
ius.user_updates
FROM sys.dm_db_index_usage_stats AS ius
JOIN sys.indexes AS i ON i.index_id = ius.index_id
AND i.object_id = ius.object_id
WHERE ius.database_id = DB_ID()
AND i.is_unique_constraint = 0 -- no unique indexes
AND i.is_primary_key = 0
AND i.is_disabled = 0
AND i.type > 1 -- don't consider heaps/clustered index
AND ( ( ius.user_seeks + ius.user_scans +
ius.user_lookups ) < ius.user_updates
OR ( ius.user_seeks = 0
AND ius.user_scans = 0
)
)
15、使用 sysprocess 查找阻塞
SELECT spid ,
status ,
blocked ,
open_tran ,
waitresource ,
waittype ,
waittime ,
cmd ,
lastwaittype
FROM master.dbo.sysprocesses
WHERE blocked <> 0
16、使用 DBCC INPUTBUFFER 返回阻塞所涉及的查询的文本
DBCC INPUTBUFFER(52)
DBCC INPUTBUFFER(53)

17、使用 sys.dm_exec_requests 和 sys.dm_exec_sessions 查找阻塞


SELECT er.session_id ,
host_name , program_name , original_login_name , er.reads ,
er.writes ,er.cpu_time , wait_type , wait_time , wait_resource ,
blocking_session_id , st.text
FROM sys.dm_exec_sessions es
LEFT JOIN sys.dm_exec_requests er
ON er.session_id = es.session_id
OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) st
WHERE blocking_session_id > 0
UNION
SELECT es.session_id , host_name , program_name , original_login_name ,
es.reads , es.writes , es.cpu_time , wait_type , wait_time ,
wait_resource , blocking_session_id , st.text
FROM sys.dm_exec_sessions es
LEFT JOIN sys.dm_exec_requests er
ON er.session_id = es.session_id
OUTER APPLY sys.dm_exec_sql_text(er.sql_handle) st
WHERE es.session_id IN ( SELECT blocking_session_id
FROM sys.dm_exec_requests
WHERE blocking_session_id > 0 )
18、查找导致通过 sys.dm_exec_connections 阻止的命令
SELECT ec.session_id ,
ec.connect_time ,
st.dbid AS DatabaseID ,
st.objectid ,
st.text
FROM sys.dm_exec_connections ec
CROSS APPLY sys.dm_exec_sql_text(ec.most_recent_sql_handle) st
WHERE session_id = 52
19、显示当前处于活动状态或已阻止的所有等待任务
SELECT blocking.session_id AS blocking_session_id ,
blocked.session_id AS blocked_session_id ,
waitstats.wait_type AS blocking_resource ,
waitstats.wait_duration_ms ,
waitstats.resource_description ,
blocked_cache.text AS blocked_text ,
blocking_cache.text AS blocking_text
FROM
sys.dm_exec_connections AS blocking
INNER JOIN sys.dm_exec_requests blocked
ON blocking.session_id = blocked.blocking_session_id
CROSS APPLY sys.dm_exec_sql_text(blocked.sql_handle)
blocked_cache
CROSS APPLY sys.dm_exec_sql_text(blocking.most_recent_sql_handle)
blocking_cache
INNER JOIN sys.dm_os_waiting_tasks waitstats
ON waitstats.session_id = blocked.session_id
20、 获取有关已知相互阻塞的进程所持有的锁
SELECT request_session_id ,
resource_type ,
DB_NAME(resource_database_id) AS DatabaseName ,
resource_associated_entity_id ,
resource_description ,
request_mode ,
request_status
FROM sys.dm_tran_locks AS dtl
WHERE request_session_id IN ( 52, 53 )
AND resource_type NOT IN ( ‘DATABASE', ‘METADATA' )

21、查找长时间运行的查询
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
22、检查索引碎片
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
23、检查阻塞的进程
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
24、sqlserver 等待统计
WITH Waits AS
(SELECT
wait_type,
wait_time_ms / 1000. AS wait_time_s,
100. * wait_time_ms / SUM(wait_time_ms) OVER() AS pct,
ROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS rn
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN (
'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE', 'SLEEP_TASK',
'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH', 'WAITFOR', 'LOGMGR_QUEUE',
'CHECKPOINT_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT',
'BROKER_TO_FLUSH',
'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT', 'CLR_AUTO_EVENT',
'DISPATCHER_QUEUE_SEMAPHORE',
'FT_IFTS_SCHEDULER_IDLE_WAIT', 'XE_DISPATCHER_WAIT', 'FT_IFTSHC_MUTEX',
'SQLTRACE_INCREMENTAL_FLUSH_SLEEP')
)
SELECT
W1.wait_type,
CAST(W1.wait_time_s AS DECIMAL(12, 2)) AS wait_time_s,
CAST(W1.pct AS DECIMAL(12, 2)) AS pct,
CAST(SUM(W2.pct) AS DECIMAL(12, 2)) AS running_pct
FROM Waits AS W1
INNER JOIN Waits AS W2 ON W2.rn <= W1.rn
GROUP BY W1.rn, W1.wait_type, W1.wait_time_s, W1.pct
HAVING SUM(W2.pct) - W1.pct < 95; -- percentage threshold
25、查找缺失的索引
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
26、监控 CPU 使用率
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;
27、缓存区缓存命中率(确认实例是否有足够内存)
SELECT
CAST((COUNT(*) * 100) AS DECIMAL(5,2)) AS BufferCacheHitRatio
FROM sys.dm_os_performance_counters
WHERE object_name = 'SQLServer:Buffer Manager'
AND counter_name = 'Buffer cache hit ratio'

28、页面预期值(较低的值可能表示内存不足)
SELECT
[object_name],
counter_name,
cntr_value
FROM
sys.dm_os_performance_counters
WHERE
[object_name] LIKE '%Manager%'
AND counter_name = 'Page life expectancy'
29、数据库大小和可用空间
EXEC sp_MSforeachdb N'USE [?];
SELECT
DB_NAME() AS [DatabaseName],
file_id,
type_desc AS [FileType],
name AS [LogicalName],
Physical_Name AS [PhysicalName],
(size * 8.0 / 1024) AS [SizeMB],
(FILEPROPERTY(name, ''SpaceUsed'') * 8.0 / 1024) AS [SpaceUsedMB],
((size - FILEPROPERTY(name, ''SpaceUsed'')) * 8.0 / 1024) AS [FreeSpaceMB]
FROM sys.master_files
WHERE
DB_NAME(database_id) = DB_NAME()
ORDER BY
type, file_id;
'
30、识别消耗 IO
SELECT
TOP 5 total_logical_reads,
total_logical_writes,
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;
31、查找死锁
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';
32、表磁盘使用情况
EXEC sp_MSforeachtable N'EXEC sp_spaceused [?]'

33、sqlserver 性能等待类型
SELECT
wait_type,
waiting_tasks_count,
wait_time_ms,
max_wait_time_ms,
signal_wait_time_ms
FROM
sys.dm_os_wait_stats
WHERE
wait_time_ms > 0
AND waiting_tasks_count > 0
ORDER BY
wait_time_ms DESC
34、查找上次修改的存储过程
SELECT
name AS [Stored Procedure],
modify_date AS [Last Modified Date]
FROM
sys.objects
WHERE
type = 'P'
AND DATEDIFF(D, modify_date, GETDATE()) < 30 -- Change 30 to the number of days
you want to go back
ORDER BY
modify_date DESC;

35、tempdb 利用率
SELECT
SUM(user_object_reserved_page_count) * 8 as [User Object Space Utilization
(KB)],
SUM(internal_object_reserved_page_count) * 8 as [Internal Object Space
Utilization (KB)],
SUM(version_store_reserved_page_count) * 8 as [Version Store Space Utilization
(KB)],
SUM(unallocated_extent_page_count) * 8 as [Free Space (KB)],
SUM(mixed_extent_page_count) * 8 as [Mixed Extent Space Utilization (KB)]
FROM
tempdb.sys.dm_db_file_space_usage;

36、查找长时间运行的事务
SELECT
transaction_id,
name,
transaction_begin_time,
transaction_type,
transaction_state
FROM
sys.dm_tran_active_transactions;

37、查询执行计划缓存
SELECT
TOP 10
qs.plan_generation_num as recompiles,
qs.execution_count,
qs.total_elapsed_time/1000000 as total_duration_secs,
qs.total_worker_time/1000000 as total_cpu_secs,
qs.total_logical_reads,
qs.total_logical_writes,
t.text AS [SQL_Text],
p.query_plan
FROM
sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) t
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) p
ORDER BY
qs.total_logical_reads DESC;

38、统计信息更新
SELECT
name AS index_name,
STATS_DATE(object_id, index_id) AS statistics_update_date
FROM
sys.indexes
WHERE
object_id = OBJECT_ID('YourTableName');

39、检查 sqlserver 代理作业


EXEC msdb.dbo.sp_help_job;
40、列出所有用户定义函数及其用法
SELECT
o.name,
o.type_desc,
(SELECT
COUNT(*)
FROM
sys.sql_expression_dependencies sed
WHERE
sed.referencing_id = o.object_id) as dependent_object_count
FROM
sys.objects o
WHERE
o.type IN ('TF', 'IF', 'FN', 'FS', 'FT')
ORDER BY
dependent_object_count DESC,
o.name;

41、识别阻塞查询
SELECT
blocking_session_id AS BlockingSessionID,
session_id AS VictimSessionID,
(SELECT text FROM sys.dm_exec_sql_text(sql_handle)) AS VictimQuery
FROM
sys.dm_exec_requests
WHERE
blocking_session_id <> 0;

42、查看锁信息
SELECT
resource_type,
resource_database_id,
resource_associated_entity_id,
request_mode,
request_type,
request_status,
request_session_id
FROM
sys.dm_tran_locks
WHERE
resource_type <> 'DATABASE';
43、查找死锁
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';

44、获取有关被阻止进程的详细信息
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;

45、活跃事务和锁
SELECT
at.transaction_id,
at.name AS transaction_name,
at.transaction_begin_time,
at.transaction_state,
at.transaction_status,
tl.request_session_id,
tl.resource_type,
tl.resource_database_id,
tl.resource_description,
tl.request_mode,
tl.request_status
FROM
sys.dm_tran_active_transactions at
JOIN
sys.dm_tran_locks tl ON at.transaction_id = tl.request_owner_id;

46、检查数据库最新备份
SELECT
database_name AS [Database],
MAX(backup_start_date) AS [Last Backup Time],
DATEDIFF(hour, MAX(backup_start_date), GETDATE()) AS [Hours Since Last Backup],
backup_size/1024/1024 AS [Backup Size (MB)]
FROM
msdb.dbo.backupset
GROUP BY
database_name,
backup_size
HAVING
MAX(backup_start_date) IS NOT NULL
ORDER BY
MAX(backup_start_date) DESC;

47、检查数据库所有备份状态
SELECT
database_name AS [Database],
backup_start_date AS [Backup Start],
backup_finish_date AS [Backup Finish],
DATEDIFF(second, backup_start_date, backup_finish_date) AS [Duration (s)],
backup_size/1024/1024 AS [Size (MB)],
[type] AS [Backup Type]
FROM
msdb.dbo.backupset
WHERE
database_name = 'YourDatabaseName' -- Specify your database name here
ORDER BY
backup_start_date DESC;

48、检查没有最近备份的数据库
WITH LastBackup AS (
SELECT
database_name,
MAX(backup_finish_date) AS last_backup
FROM
msdb.dbo.backupset
GROUP BY
database_name
)
SELECT
name AS [Database]
FROM
sys.databases db
LEFT JOIN
LastBackup lb ON db.name = lb.database_name
WHERE
db.state = 0 -- Only consider online databases
AND (
lb.last_backup IS NULL
OR DATEDIFF(hour, lb.last_backup, GETDATE()) > 48 -- Consider as not recent
if more than 48 hours old
)
ORDER BY
db.name;

49、识别碎片索引
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;

50、重建索引
ALTER INDEX [YourIndexName] ON [YourSchema].[YourTableName]
REBUILD;

重组索引:
ALTER INDEX [YourIndexName] ON [YourSchema].[YourTableName]
REORGANIZE;

更新统计信息
UPDATE STATISTICS [YourSchema].[YourTableName] [YourIndexName]

重建数据库中所有索引
EXEC sp_MSForEachTable 'ALTER INDEX ALL ON ? REBUILD'

-- Disable the index


ALTER INDEX [YourIndexName] ON [YourSchema].[YourTableName] DISABLE

-- Rebuild the index


ALTER INDEX [YourIndexName] ON [YourSchema].[YourTableName] REBUILD

---分区信息
SELECT
name AS PartitionFunction,
type_desc,
fanout,
create_date,
modify_date
FROM
sys.partition_functions;

---分区方案
SELECT
name AS PartitionScheme,
type_desc,
fanout,
create_date,
modify_date
FROM
sys.partition_schemes;

51、根据碎片级别有条件的重建或重组
DECLARE @TableName NVARCHAR(255)
DECLARE @SchemaName NVARCHAR(255)
DECLARE @IndexName NVARCHAR(255)
DECLARE @FragPercent DECIMAL

DECLARE IndexCursor CURSOR FOR


SELECT
OBJECT_SCHEMA_NAME(ips.[object_id]) as SchemaName,
OBJECT_NAME(ips.[object_id]) as TableName,
si.name as IndexName,
ips.avg_fragmentation_in_percent
FROM
sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') ips
JOIN
sys.indexes si ON ips.[object_id] = si.[object_id]
AND ips.index_id = si.index_id
WHERE
ips.avg_fragmentation_in_percent > 10 -- Consider indexes with more than
10% fragmentation
ORDER BY
ips.avg_fragmentation_in_percent DESC
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

FETCH NEXT FROM IndexCursor INTO @SchemaName, @TableName, @IndexName,


@FragPercent
END

CLOSE IndexCursor
DEALLOCATE IndexCursor

52、检查分区表和索引
SELECT
OBJECT_NAME(i.object_id) AS TableName,
i.name AS IndexName,
p.partition_number,
fg.name AS FileGroupName,
p.rows,
au.total_pages AS TotalPages
FROM
sys.partitions p
JOIN
sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id
JOIN
sys.allocation_units au ON p.hobt_id = au.container_id
JOIN
sys.filegroups fg ON au.data_space_id = fg.data_space_id
WHERE
p.data_compression > 0
ORDER BY
OBJECT_NAME(i.object_id),
p.partition_number;

53、检查分区范围行
SELECT
OBJECT_NAME(p.object_id) AS TableName,
i.name AS IndexName,
p.partition_number,
pr.value AS BoundaryValue,
p.rows AS [RowCount]
FROM
sys.partitions p
JOIN
sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id
LEFT JOIN
sys.partition_range_values pr ON p.partition_number = pr.boundary_id AND
pr.function_id = i.data_space_id
WHERE
OBJECT_NAME(p.object_id) = 'YourTableName' -- Specify the table name here
ORDER BY
p.partition_number;

54、所有数据库的 CPU 资源使用情况


WITH DB_CPU_STATS_ON_INSTANCE
AS
(SELECT DatabaseID, DB_Name(DatabaseID) AS [DatabaseName], SUM(total_worker_time)
AS [CPU_Time_Ms]
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY (SELECT CONVERT(int, value) AS [DatabaseID]
FROM sys.dm_exec_plan_attributes(qs.plan_handle)
WHERE attribute = N'dbid') AS F_DB
GROUP BY DatabaseID)
SELECT ROW_NUMBER() OVER(ORDER BY [CPU_Time_Ms] DESC) AS [row_num],
DatabaseName, [CPU_Time_Ms],
CAST([CPU_Time_Ms] * 1.0 / SUM([CPU_Time_Ms]) OVER() * 100.0 AS DECIMAL(5, 2)) AS
[CPUPercent]
FROM DB_CPU_STATS_ON_INSTANCE
WHERE DatabaseID > 4
AND DatabaseID <> 32767
ORDER BY row_num OPTION (RECOMPILE);

55、查询在 SQL Server 数据库中找到 TOP CPU 查询


SELECT TOP 50
ObjectName = OBJECT_SCHEMA_NAME(qt.objectid,dbid) + '.' +
OBJECT_NAME(qt.objectid, qt.dbid)
,TextData = qt.text
,DiskReads = qs.total_physical_reads -- The worst reads, disk reads
,MemoryReads = qs.total_logical_reads --Logical Reads are memory
reads
,Executions = qs.execution_count
,TotalCPUTime = qs.total_worker_time
,AverageCPUTime = qs.total_worker_time/qs.execution_count
,DiskWaitAndCPUTime = qs.total_elapsed_time
,MemoryWrites = qs.max_logical_writes
,DateCached = qs.creation_time
,DatabaseName = DB_Name(qt.dbid)
,LastExecutionTime = qs.last_execution_time
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
ORDER BY qs.total_worker_time DESC;

select top 50
query_stats.query_hash,
SUM(query_stats.total_worker_time) / SUM(query_stats.execution_count) as
avgCPU_USAGE,
min(query_stats.statement_text) as QUERY
from (
select qs.*,
SUBSTRING(st.text,(qs.statement_start_offset/2)+1,
((case statement_end_offset
when -1 then DATALENGTH(st.text)
else qs.statement_end_offset end
- qs.statement_start_offset)/2) +1) as statement_text
from sys.dm_exec_query_stats as qs
cross apply sys.dm_exec_sql_text(qs.sql_handle) as st
) as query_stats
group by query_stats.query_hash
order by 2 desc;

56、查询在 SQL Server 数据库中找到 TOP 50 IO 查询


select
q.[text],
SUBSTRING(q.text, (highest_cpu_queries.statement_start_offset/2)+1,
((CASE highest_cpu_queries.statement_end_offset
WHEN -1 THEN DATALENGTH(q.text)
ELSE highest_cpu_queries.statement_end_offset
END - highest_cpu_queries.statement_start_offset)/2) + 1) AS
statement_text,

highest_cpu_queries.total_worker_time,
highest_cpu_queries.total_logical_reads,
highest_cpu_queries.last_execution_time,
highest_cpu_queries.execution_count,
q.dbid,
q.objectid,
q.number,
q.encrypted,
highest_cpu_queries.plan_handle
from
(select top 50
qs.last_execution_time,
qs.execution_count,
qs.plan_handle,
qs.total_worker_time,
qs.statement_start_offset,
qs.statement_end_offset,
qs.total_logical_reads
from
sys.dm_exec_query_stats qs
order by qs.total_worker_time desc) as highest_cpu_queries
cross apply sys.dm_exec_sql_text(plan_handle) as q
order by highest_cpu_queries.total_logical_reads desc;

查询在 SQL Server 数据库中找到 TOP IO 查询


select
SUBSTRING(st.text,(qs.statement_start_offset/2)+1,
((case statement_end_offset
when -1 then DATALENGTH(st.text)
else qs.statement_end_offset end
- qs.statement_start_offset)/2) +1) as statement_text,
qs.total_logical_reads,
qs.total_physical_reads,
qs.execution_count
from sys.dm_exec_query_stats as qs
cross apply sys.dm_exec_sql_text(qs.sql_handle) as st
order by qs.total_logical_reads desc, qs.execution_count desc;

查看 IO 统计数据和以下信息
select
serverproperty('MachineName') 'machine_name'
,isnull(serverproperty('InstanceName'),'mssqlserver') 'instance_name'
,@@SERVERNAME 'sql_server_name'
,DB_NAME(mf.database_id) 'database_name'
,mf.name 'logical_name'
,mf.physical_name 'physical_name'
,left(mf.physical_name,1) 'disk_drive'
,mf.type_desc 'file_type'
,mf.state_desc 'state'
,case mf.is_read_only
when 0 then 'no'
when 1 then 'yes'
end 'read_only'
,convert(numeric(18,2),convert(numeric,mf.size)*8/1024) 'size_mb'
,divfs.size_on_disk_bytes/1024/1024 'size_on_disk_mb'
,case mf.is_percent_growth
when 0 then cast(convert(int,convert(numeric,mf.growth)*8/1024) as varchar) + ' MB'
when 1 then cast(mf.growth as varchar) + '%'
end 'growth'
,case mf.is_percent_growth
when 0 then convert(numeric(18,2),convert(numeric,mf.growth)*8/1024)
when 1 then convert(numeric(18,2),(convert(numeric,mf.size)*mf.growth/100)*8/1024)
end 'next_growth_mb'
,case mf.max_size
when 0 then 'NO-growth'
when -1 then (case mf.growth when 0 then 'NO-growth' else 'unlimited' end)
else cast(convert(int,convert(numeric,mf.max_size)*8/1024) as varchar)+' MB'
end 'max_size'

,divfs.num_of_reads
,divfs.num_of_bytes_read/1024/1024 'read_mb'
,divfs.io_stall_read_ms

,divfs.num_of_writes
,divfs.num_of_bytes_written/1024/1024 'write_mb'
,divfs.io_stall_write_ms

from sys.master_files as mf
left outer join sys.dm_io_virtual_file_stats(null,null) as divfs
on mf.database_id=divfs.database_id and mf.file_id=divfs.file_id;

监视 SQL Server 中正在运行的查询


select text,
SUBSTRING(st.text, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2) + 1) AS statement_text,
* from sys.dm_exec_requests qs
cross apply sys.dm_exec_sql_text(sql_handle) st
cross apply sys.dm_exec_query_plan(plan_handle);

SQL Server 阻塞和锁定脚本


SELECT
db.name DBName,
tl.request_session_id,
wt.blocking_session_id,
OBJECT_NAME(p.OBJECT_ID) BlockedObjectName,
tl.resource_type,
h1.TEXT AS RequestingText,
h2.TEXT AS BlockingTest,
tl.request_mode
FROM sys.dm_tran_locks AS tl
INNER JOIN sys.databases db ON db.database_id = tl.resource_database_id
INNER JOIN sys.dm_os_waiting_tasks AS wt ON tl.lock_owner_address =
wt.resource_address
INNER JOIN sys.partitions AS p ON p.hobt_id = tl.resource_associated_entity_id
INNER JOIN sys.dm_exec_connections ec1 ON ec1.session_id = tl.request_session_id
INNER JOIN sys.dm_exec_connections ec2 ON ec2.session_id = wt.blocking_session_id
CROSS APPLY sys.dm_exec_sql_text(ec1.most_recent_sql_handle) AS h1
CROSS APPLY sys.dm_exec_sql_text(ec2.most_recent_sql_handle) AS h2
GO

每天检查备份
SELECT DB.name AS Database_Name
,MAX(DB.recovery_model_desc) AS Recovery_Model
,MAX(BS.backup_start_date) AS Last_Backup
,MAX(CASE WHEN BS.type = 'D'
THEN BS.backup_start_date END)
AS Last_Full_backup
,SUM(CASE WHEN BS.type = 'D'
THEN 1 END)
AS Count_Full_backup
,MAX(CASE WHEN BS.type = 'L'
THEN BS.backup_start_date END)
AS Last_Log_backup
,SUM(CASE WHEN BS.type = 'L'
THEN 1 END)
AS Count_Log_backup
,MAX(CASE WHEN BS.type = 'I'
THEN BS.backup_start_date END)
AS Last_Differential_backup
,SUM(CASE WHEN BS.type = 'I'
THEN 1 END)
AS Count_Differential_backup
,MAX(CASE WHEN BS.type = 'F'
THEN BS.backup_start_date END)
AS LastFile
,SUM(CASE WHEN BS.type = 'F'
THEN 1 END)
AS CountFile
,MAX(CASE WHEN BS.type = 'G'
THEN BS.backup_start_date END)
AS LastFileDiff
,SUM(CASE WHEN BS.type = 'G'
THEN 1 END)
AS CountFileDiff
,MAX(CASE WHEN BS.type = 'P'
THEN BS.backup_start_date END)
AS LastPart
,SUM(CASE WHEN BS.type = 'P'
THEN 1 END)
AS CountPart
,MAX(CASE WHEN BS.type = 'Q'
THEN BS.backup_start_date END)
AS LastPartDiff
,SUM(CASE WHEN BS.type = 'Q'
THEN 1 END)
AS CountPartDiff
FROM sys.databases AS DB
LEFT JOIN
msdb.dbo.backupset AS BS
ON BS.database_name = DB.name
WHERE ISNULL(BS.is_damaged, 0) = 0-- exclude damaged backups
GROUP BY DB.name
ORDER BY Last_Backup desc;

索引维护脚本(在第一行正确输入 SQL Server 数据库名称,查询就会找到碎片索引)


declare @db int
select @db=DB_ID('DEVECI')
select 'ALTER INDEX [' + i.name +'] on '+OBJECT_NAME(s.object_id)+' REBUILD WITH
(ONLINE = ON)',
objname = OBJECT_NAME(s.object_id),
s.object_id,
index_name= i.name,
index_type_desc,
avg_fragmentation_in_percent
from sys.dm_db_index_physical_stats(@db,null,null,null,null) as s
join sys.indexes i on i.object_id = s.object_id and i.index_id = s.index_id
where avg_fragmentation_in_percent>30
order by avg_fragmentation_in_percent desc, page_count desc;

所有索引的使用情况统计信息
select objname = OBJECT_NAME(s.object_id),
s.object_id,
index_name= i.name,
index_id = i.index_id,
user_seeks, user_scans, user_lookups
from sys.dm_db_index_usage_stats as s
join sys.indexes i on i.object_id = s.object_id and i.index_id = s.index_id
where database_id = DB_ID('DEVECI')
and OBJECTPROPERTY(s.object_id,'IsUserTable')=1
order by (user_seeks + user_scans + user_lookups) desc;

检查所有数据库对象的统计信息
SELECT
object_name(si.[object_id]) AS [TableName]
, CASE
WHEN si.[stats_id] = 0 then 'Heap'
WHEN si.[stats_id] = 1 then 'CL'
WHEN INDEXPROPERTY ( si.[object_id], si.[name], 'IsAutoStatistics') = 1 THEN
'Stats-Auto'
WHEN INDEXPROPERTY ( si.[object_id], si.[name], 'IsHypothetical') = 1 THEN 'Stats-
HIND'
WHEN INDEXPROPERTY ( si.[object_id], si.[name], 'IsStatistics') = 1 THEN 'Stats-
User'
WHEN si.[stats_id] BETWEEN 2 AND 1004 THEN 'NC ' + RIGHT('00' + convert(varchar,
si.[stats_id]), 3)
ELSE 'Text/Image'
END AS [IndexType]
, si.[name] AS [IndexName]
, si.[stats_id] AS [IndexID]
, CASE
WHEN si.[stats_id] BETWEEN 1 AND 250 AND STATS_DATE (si.[object_id], si.[stats_id])
< DATEADD(m, -1, getdate())
THEN '!! More than a month OLD !!'
WHEN si.[stats_id] BETWEEN 1 AND 250 AND STATS_DATE (si.[object_id], si.[stats_id])
< DATEADD(wk, -1, getdate())
THEN '! Within the past month !'
WHEN si.[stats_id] BETWEEN 1 AND 250 THEN 'Stats recent'
ELSE ''
END AS [Warning]
, STATS_DATE (si.[object_id], si.[stats_id]) AS [Last Stats Update]
, no_recompute
FROM sys.stats AS si
WHERE OBJECTPROPERTY(si.[object_id], 'IsUserTable') = 1 and STATS_DATE (si.
[object_id], si.[stats_id]) is not null
AND (INDEXPROPERTY ( si.[object_id], si.[name], 'IsAutoStatistics') = 1
OR INDEXPROPERTY ( si.[object_id], si.[name], 'IsHypothetical') = 1
OR INDEXPROPERTY ( si.[object_id], si.[name], 'IsStatistics') = 1)
ORDER BY [Last Stats Update]
go

活动会话和状态
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

SELECT
SPID = er.session_id
,BlkBy = er.blocking_session_id
,ElapsedMS = er.total_elapsed_time
,CPU = er.cpu_time
,IOReads = er.logical_reads + er.reads
,IOWrites = er.writes
,Executions = ec.execution_count
,CommandType = er.command
,ObjectName = OBJECT_SCHEMA_NAME(qt.objectid,dbid) + '.' + OBJECT_NAME(qt.objectid,
qt.dbid)
,SQLStatement =
SUBSTRING
(
qt.text,
er.statement_start_offset/2,
(CASE WHEN er.statement_end_offset = -1
THEN LEN(CONVERT(nvarchar(MAX), qt.text)) * 2
ELSE er.statement_end_offset
END - er.statement_start_offset)/2
)
,Status = ses.status
,[Login] = ses.login_name
,Host = ses.host_name
,DBName = DB_Name(er.database_id)
,LastWaitType = er.last_wait_type
,StartTime = er.start_time
,Protocol = con.net_transport
,transaction_isolation =
CASE ses.transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'Read Uncommitted'
WHEN 2 THEN 'Read Committed'
WHEN 3 THEN 'Repeatable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot'
END
,ConnectionWrites = con.num_writes
,ConnectionReads = con.num_reads
,ClientAddress = con.client_net_address
,Authentication = con.auth_scheme
FROM sys.dm_exec_requests er
LEFT JOIN sys.dm_exec_sessions ses ON ses.session_id = er.session_id
LEFT JOIN sys.dm_exec_connections con ON con.session_id = ses.session_id
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) as qt
OUTER APPLY
(
SELECT execution_count = MAX(cp.usecounts)
FROM sys.dm_exec_cached_plans cp
WHERE cp.plan_handle = er.plan_handle
) ec
ORDER BY
er.blocking_session_id DESC,
er.logical_reads + er.reads DESC,
er.session_id;

SQL Server 等待事件


select wt.session_id, wt.exec_context_id, wt.wait_duration_ms, wt.wait_type,
wt.blocking_session_id, wt.resource_address, wt.resource_description,
s.program_name, st.text, sp.query_plan, s.cpu_time cpu_time_ms, s.memory_usage*8
memory_usage_kb
from sys.dm_os_waiting_tasks wt
join sys.dm_exec_sessions s on s.session_id=wt.session_id
join sys.dm_exec_requests r on r.session_id=s.session_id
outer apply sys.dm_exec_sql_text(r.sql_handle) st
outer apply sys.dm_exec_query_plan(r.plan_handle) sp
where s.is_user_process=1
order by wt.session_id, wt.exec_context_id;

查询找到数据库的等待事件
SELECT getdate() as 'Run_Time' --script running time
, wait_type --wait type
,waiting_tasks_count
, CAST(wait_time_ms / 1000. AS DECIMAL(12, 2)) AS wait_time_s --saniye
cinsinden bekleme zamaný
, CAST(100. * wait_time_ms / SUM(wait_time_ms) OVER() AS DECIMAL(12, 2)) AS
pct --toplam beklemeye oraný
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN
('BROKER_TASK_STOP','Total','SLEEP','BROKER_EVENTHANDLER','BROKER_RECEIVE_WAITFOR',

'BROKER_TRANSMITTER','CHECKPOINT_QUEUE','CHKPT,CLR_AUTO_EVENT','CLR_MANUAL_EVENT','
KSOURCE_WAKEUP','LAZYWRITER_SLEEP',

'LOGMGR_QUEUE','ONDEMAND_TASK_QUEUE','REQUEST_FOR_DEADLOCK_SEARCH','RESOURCE_QUEUE'
,'SERVER_IDLE_CHECK',

'SLEEP_BPOOL_FLUSH','SLEEP_DBSTARTUP','SLEEP_DCOMSTARTUP','SLEEP_MSDBSTARTUP','SLEE
P_SYSTEMTASK','SLEEP_TASK',

'SLEEP_TEMPDBSTARTUP','SNI_HTTP_ACCEPT','SQLTRACE_BUFFER_FLUSH','TRACEWRITE','WAIT_
FOR_RESULTS','WAITFOR_TASKSHUTDOWN',
'XE_DISPATCHER_WAIT','XE_TIMER_EVENT','WAITFOR')
ORDER BY 4 DESC

数据库的等待事件
with waits as
(select
wait_type,
wait_time_ms / 1000.0 as waits,
(wait_time_ms - signal_wait_time_ms) / 1000.0 as resources,
signal_wait_time_ms / 1000.0 as signals,
waiting_tasks_count as waitcount,
100.0 * wait_time_ms / sum (wait_time_ms) over() as percentage,
row_number() over(order by wait_time_ms desc) as rownum
from sys.dm_os_wait_stats
where wait_type not in (
N'CLR_SEMAPHORE', N'LAZYWRITER_SLEEP',
N'RESOURCE_QUEUE', N'SQLTRACE_BUFFER_FLUSH',
N'SLEEP_TASK', N'SLEEP_SYSTEMTASK',
N'WAITFOR', N'HADR_FILESTREAM_IOMGR_IOCOMPLETION',
N'CHECKPOINT_QUEUE', N'REQUEST_FOR_DEADLOCK_SEARCH',
N'XE_TIMER_EVENT', N'XE_DISPATCHER_JOIN',
N'LOGMGR_QUEUE', N'FT_IFTS_SCHEDULER_IDLE_WAIT',
N'BROKER_TASK_STOP', N'CLR_MANUAL_EVENT',
N'CLR_AUTO_EVENT', N'DISPATCHER_QUEUE_SEMAPHORE',
N'TRACEWRITE', N'XE_DISPATCHER_WAIT',
N'BROKER_TO_FLUSH', N'BROKER_EVENTHANDLER',
N'FT_IFTSHC_MUTEX', N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
N'DIRTY_PAGE_POLL', N'SP_SERVER_DIAGNOSTICS_SLEEP')
)
select
w1.wait_type as waittype,
cast (w1.waits as decimal(14, 2)) wait_s,
cast (w1.resources as decimal(14, 2)) resource_s,
cast (w1.signals as decimal(14, 2)) signal_s,
w1.waitcount wait_count,
cast (w1.percentage as decimal(4, 2)) percentage,
cast ((w1.waits / w1.waitcount) as decimal (14, 4)) avgWait_s,
cast ((w1.resources / w1.waitcount) as decimal (14, 4)) avgResource_s,
cast ((w1.signals / w1.waitcount) as decimal (14, 4)) avgSignal_s
from waits as w1
inner join waits as w2 on w2.rownum <= w1.rownum
group by w1.rownum, w1.wait_type, w1.waits, w1.resources, w1.signals, w1.waitcount,
w1.percentage
having sum (w2.percentage) - w1.percentage < 95; -- percentage threshold

通过备份历史记录分析数据库大小的增长
DECLARE @startDate datetime;
SET @startDate = GetDate();

SELECT PVT.DatabaseName
, PVT.[0], PVT.[-1], PVT.[-2], PVT.[-3], PVT.[-4], PVT.[-5], PVT.[-6]
, PVT.[-7], PVT.[-8], PVT.[-9], PVT.[-10], PVT.[-11], PVT.[-12]
FROM
(SELECT BS.database_name AS DatabaseName
,DATEDIFF(mm, @startDate, BS.backup_start_date) AS MonthsAgo
,CONVERT(numeric(10, 1), AVG(BF.file_size / 1048576.0)) AS AvgSizeMB
FROM msdb.dbo.backupset as BS
INNER JOIN
msdb.dbo.backupfile AS BF
ON BS.backup_set_id = BF.backup_set_id
WHERE NOT BS.database_name IN
('master', 'msdb', 'model', 'tempdb')
AND BF.[file_type] = 'D'
AND BS.backup_start_date BETWEEN DATEADD(yy, -1, @startDate) AND @startDate
GROUP BY BS.database_name
,DATEDIFF(mm, @startDate, BS.backup_start_date)
) AS BCKSTAT
PIVOT (SUM(BCKSTAT.AvgSizeMB)
FOR BCKSTAT.MonthsAgo IN ([0], [-1], [-2], [-3], [-4], [-5], [-6], [-7], [-8], [-
9], [-10], [-11], [-12])
) AS PVT
ORDER BY PVT.DatabaseName;

检查 SQL Server 中的表是否已分区


select distinct
pp.[object_id],
TbName = OBJECT_NAME(pp.[object_id]),
index_name = i.[name],
index_type_desc = i.type_desc,
partition_scheme = ps.[name],
data_space_id = ps.data_space_id,
function_name = pf.[name],
function_id = ps.function_id
from sys.partitions pp
inner join sys.indexes i
on pp.[object_id] = i.[object_id]
and pp.index_id = i.index_id
inner join sys.data_spaces ds
on i.data_space_id = ds.data_space_id
inner join sys.partition_schemes ps
on ds.data_space_id = ps.data_space_id
inner JOIN sys.partition_functions pf
on ps.function_id = pf.function_id
order by TbName, index_name ;

select getdate() Date_Collected


,serverproperty('MachineName') 'Machine_Name'
,isnull(serverproperty('InstanceName'),'mssqlserver') 'Instance_Name'
,@@SERVERNAME 'Sql_Server_Name'
,SERVERPROPERTY('productversion') Product_Version
,SERVERPROPERTY ('productlevel') Product_Level
,SERVERPROPERTY ('edition') 'Edition'
,d.name 'database_name'
,suser_sname(d.owner_sid) 'owner'
,ls.cntr_value as [log_size_kb]
,lu.cntr_value as [log_used_kb]
,lp.cntr_value as [percent_log_used]
,ds.cntr_value as [data_files_size_kb]
from sys.databases d
left outer join sys.dm_os_performance_counters as lu on
lu.instance_name=d.name and lu.counter_name like N'Log File(s) Used Size (KB)%'
left outer join sys.dm_os_performance_counters as ls on
ls.instance_name=d.name and ls.counter_name like N'Log File(s) Size (KB)%' and
ls.cntr_value > 0
left outer join sys.dm_os_performance_counters as lp on
lp.instance_name=d.name and lp.counter_name like N'Percent Log Used%'
left outer join sys.dm_os_performance_counters as ds on
ds.instance_name=d.name and ds.counter_name like N'Data File(s) Size (KB)%'
order by d.name;

select
serverproperty('MachineName') 'machine_name'
,isnull(serverproperty('InstanceName'),'mssqlserver') 'instance_name'
,@@SERVERNAME 'sql_server_name'
,d.name 'database_name'
,suser_sname(d.owner_sid) 'owner'
,d.compatibility_level
,d.collation_name
,d.is_auto_close_on
,d.is_auto_shrink_on
,d.state_desc
,d.snapshot_isolation_state
,d.is_read_committed_snapshot_on
,d.recovery_model_desc
,d.is_auto_create_stats_on
,d.is_auto_update_stats_on
,d.is_auto_update_stats_async_on
,d.is_in_standby
,d.page_verify_option_desc
,d.log_reuse_wait_desc
,ls.cntr_value as [log size (kb)]
,lu.cntr_value as [log used (kb)]
,lp.cntr_value as [percent log used]
,ds.cntr_value as [data file(s) size (kb)]
from sys.databases d
inner join sys.dm_os_performance_counters as lu on lu.instance_name=d.name
and lu.counter_name like N'Log File(s) Used Size (KB)%'
inner join sys.dm_os_performance_counters as ls on ls.instance_name=d.name
and ls.counter_name like N'Log File(s) Size (KB)%' and ls.cntr_value > 0
inner join sys.dm_os_performance_counters as lp on lp.instance_name=d.name
and lp.counter_name like N'Percent Log Used%'
inner join sys.dm_os_performance_counters as ds on ds.instance_name=d.name
and ds.counter_name like N'Data File(s) Size (KB)%'
order by d.name

找到所有索引的使用情况统计信息
select objname = OBJECT_NAME(s.object_id),
s.object_id,
index_name= i.name,
index_id = i.index_id,
user_seeks, user_scans, user_lookups
from sys.dm_db_index_usage_stats as s
join sys.indexes i on i.object_id = s.object_id and i.index_id = s.index_id
where database_id = DB_ID('DEVECI')
and OBJECTPROPERTY(s.object_id,'IsUserTable')=1
order by (user_seeks + user_scans + user_lookups) desc;

21、性能计数器
• SQL Server: Buffer manager—buffer cache hit ratio
• SQL Server: Buffer manager—page life expectancy
• SQL Server: Memory manager—total server memory (KB)
• SQL Server: Memory manager—target server memory (KB)
• SQL Server: Memory manager—memory grants pending
• SQL Server: Access methods—full scans/sec
• SQL Server: Access methods—index searches/sec
• SQL Server: Access methods—forwarded records/sec
• SQL Server: SQL statistics—SQL compilations/sec
• SQL Server: SQL statistics—batch requests/sec
• SQL Server: General statistics—user connections
• SQL Server: Locks—Lock Waits/sec
• SQL Server: Locks—Number of Deadlocks/sec
SELECT * FROM sys.dm_exec_requests er
JOIN sys.dm_exec_sessions es
ON er.session_id = es.session_id-- remove all system sessions and yourself
WHERE es.session_id > 50 and es.session_id != @@SPID

• sys.dm_io_virtual_file_stats
• sys.dm_db_index_physical_stats
• sys.dm_db_index_usage_stats
• sys.dm_db_missing_index_details
• sys.dm_os_wait_stats
• sys.dm_os_sys_memory
• sys.dm_os_process_memory

You might also like