sqlserver 脚本
sqlserver 脚本
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
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)
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');
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'
---分区信息
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
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
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;
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;
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;
查看 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;
每天检查备份
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;
所有索引的使用情况统计信息
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;
查询找到数据库的等待事件
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;
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