外观
SQLServer 性能监控视图
监控视图概述
监控视图的作用
SQLServer 监控视图提供了实时访问数据库内部状态和性能数据的能力,帮助数据库管理员和开发人员:
- 识别性能瓶颈和问题
- 监控系统资源使用情况
- 分析查询性能
- 检测和解决并发问题
- 监控高可用状态
- 确保数据库安全
动态管理视图 (DMVs) 概述
动态管理视图 (DMVs) 是 SQLServer 提供的一组系统视图,用于返回服务器状态信息,帮助监控服务器实例的健康状况、诊断问题和优化性能。DMVs 以 sys.dm_ 前缀命名,分为以下几类:
- 服务器范围的 DMVs:以
sys.dm_os_、sys.dm_server_等前缀命名 - 数据库范围的 DMVs:以
sys.dm_db_前缀命名 - 执行相关的 DMVs:以
sys.dm_exec_前缀命名 - 事务相关的 DMVs:以
sys.dm_tran_前缀命名
系统视图概述
系统视图是 SQLServer 提供的一组预定义视图,用于访问系统元数据和配置信息。系统视图以 sys. 前缀命名,例如:
sys.databases:数据库信息sys.tables:表信息sys.indexes:索引信息sys.procedures:存储过程信息
监控视图使用建议
- 权限控制:DMVs 需要
VIEW SERVER STATE或VIEW DATABASE STATE权限,应严格控制访问权限 - 避免频繁查询:某些 DMVs 查询可能会对性能产生影响,避免在生产环境频繁执行
- 结合使用:将 DMVs 与系统视图结合使用,获取更全面的信息
- 定期收集数据:建立性能基线,便于比较和分析性能变化
- 使用监控工具:结合 SSMS、Azure Data Studio 或第三方监控工具,提高监控效率
性能相关 DMVs
CPU 性能监控
主要 DMVs:
sys.dm_os_ring_buffers:系统环形缓冲区,包含 CPU 使用情况sys.dm_os_performance_counters:性能计数器,包含 CPU 相关指标sys.dm_exec_query_stats:查询统计信息,包含 CPU 时间sys.dm_os_process_memory:进程内存使用情况
监控查询示例:
sql
-- 查询当前 CPU 使用率
SELECT
TOP 10
wait_type,
wait_time_ms / 1000.0 AS wait_time_seconds,
signal_wait_time_ms / 1000.0 AS signal_wait_time_seconds,
wait_time_ms - signal_wait_time_ms AS resource_wait_time_ms
FROM sys.dm_os_wait_stats
WHERE wait_type NOT IN (
'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE',
'SLEEP_TASK', 'SLEEP_SYSTEMTASK', 'WAITFOR',
'BROKER_TASK_STOP', 'BROKER_RECEIVE_WAITFOR',
'CHECKPOINT_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH',
'XE_TIMER_EVENT', 'BROKER_EVENTHANDLER',
'FT_IFTS_SCHEDULER_IDLE_WAIT', 'XE_DISPATCHER_WAIT',
'XE_DISPATCHER_JOIN')
ORDER BY wait_time_ms DESC;
-- 查询 CPU 使用率最高的查询
SELECT
TOP 10
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 query_text,
qs.execution_count,
qs.total_worker_time / 1000000.0 AS total_cpu_seconds,
qs.total_worker_time / qs.execution_count / 1000000.0 AS avg_cpu_seconds
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY total_cpu_seconds DESC;内存性能监控
主要 DMVs:
sys.dm_os_memory_clerks:内存分配器信息sys.dm_os_memory_objects:内存对象信息sys.dm_os_sys_memory:系统内存信息sys.dm_os_process_memory:SQL Server 进程内存使用情况sys.dm_os_ring_buffers:内存压力相关信息
监控查询示例:
sql
-- 查询内存使用情况
SELECT
type,
name,
SUM(pages_kb) / 1024.0 AS memory_mb
FROM sys.dm_os_memory_clerks
GROUP BY type, name
ORDER BY memory_mb DESC;
-- 查询缓冲池使用情况
SELECT
COUNT(*) * 8 / 1024.0 AS cached_data_mb,
SUM(CASE WHEN is_modified = 1 THEN 1 ELSE 0 END) * 8 / 1024.0 AS modified_data_mb
FROM sys.dm_os_buffer_descriptors;I/O 性能监控
主要 DMVs:
sys.dm_io_virtual_file_stats:数据库文件 I/O 统计信息sys.dm_os_wait_stats:等待统计信息,包含 I/O 等待sys.dm_io_pending_io_requests:挂起的 I/O 请求
监控查询示例:
sql
-- 查询数据库文件 I/O 统计信息
SELECT
DB_NAME(vfs.database_id) AS database_name,
mf.name AS file_name,
mf.type_desc AS file_type,
vfs.num_of_reads,
vfs.num_of_writes,
vfs.total_bytes_read / 1024.0 / 1024.0 AS total_read_mb,
vfs.total_bytes_written / 1024.0 / 1024.0 AS total_written_mb,
vfs.io_stall_read_ms / NULLIF(vfs.num_of_reads, 0) AS avg_read_latency_ms,
vfs.io_stall_write_ms / NULLIF(vfs.num_of_writes, 0) AS avg_write_latency_ms
FROM sys.dm_io_virtual_file_stats(NULL, NULL) vfs
JOIN sys.master_files mf ON vfs.database_id = mf.database_id AND vfs.file_id = mf.file_id
ORDER BY database_name, file_type;
-- 查询 I/O 等待统计信息
SELECT
wait_type,
wait_time_ms / 1000.0 AS wait_time_seconds,
waiting_tasks_count
FROM sys.dm_os_wait_stats
WHERE wait_type LIKE 'PAGEIOLATCH%' OR wait_type LIKE 'WRITELOG'
ORDER BY wait_time_seconds DESC;查询性能 DMVs
慢查询监控
主要 DMVs:
sys.dm_exec_query_stats:查询统计信息sys.dm_exec_sql_text:SQL 文本sys.dm_exec_query_plan:执行计划
监控查询示例:
sql
-- 查询执行时间最长的查询
SELECT
TOP 10
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 query_text,
qs.execution_count,
qs.total_elapsed_time / 1000000.0 AS total_elapsed_seconds,
qs.total_elapsed_time / qs.execution_count / 1000000.0 AS avg_elapsed_seconds,
qs.total_logical_reads,
qs.total_logical_writes
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY total_elapsed_seconds DESC;执行计划监控
主要 DMVs:
sys.dm_exec_query_plan:缓存的执行计划sys.dm_exec_cached_plans:缓存的计划信息sys.dm_exec_query_plan_stats:实际执行的计划统计信息
监控查询示例:
sql
-- 查询缓存的执行计划
SELECT
cp.usecounts AS plan_use_count,
cp.size_in_bytes / 1024.0 AS plan_size_kb,
st.text AS query_text,
qp.query_plan
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) qp
WHERE st.text LIKE '%SELECT%' -- 替换为你要查找的查询模式
ORDER BY cp.usecounts DESC;索引使用情况
主要 DMVs:
sys.dm_db_index_usage_stats:索引使用统计信息sys.dm_db_missing_index_details:缺失索引详细信息sys.dm_db_missing_index_groups:缺失索引组
监控查询示例:
sql
-- 查询索引使用情况
SELECT
OBJECT_NAME(i.object_id) AS table_name,
i.name AS index_name,
i.type_desc AS index_type,
COALESCE(ius.user_seeks, 0) AS user_seeks,
COALESCE(ius.user_scans, 0) AS user_scans,
COALESCE(ius.user_lookups, 0) AS user_lookups,
COALESCE(ius.user_updates, 0) AS user_updates
FROM sys.indexes i
LEFT JOIN sys.dm_db_index_usage_stats ius
ON i.object_id = ius.object_id AND i.index_id = ius.index_id
WHERE OBJECTPROPERTY(i.object_id, 'IsUserTable') = 1
ORDER BY user_seeks + user_scans + user_lookups DESC;
-- 查询缺失索引
SELECT
OBJECT_NAME(mid.object_id) AS table_name,
mid.equality_columns,
mid.inequality_columns,
mid.included_columns,
migs.avg_total_user_cost,
migs.avg_user_impact,
migs.user_seeks + migs.user_scans AS total_usage
FROM sys.dm_db_missing_index_details mid
INNER JOIN sys.dm_db_missing_index_groups mig ON mid.index_handle = mig.index_handle
INNER JOIN sys.dm_db_missing_index_group_stats migs ON mig.index_group_handle = migs.group_handle
ORDER BY total_usage * migs.avg_user_impact DESC;并发相关 DMVs
锁监控
主要 DMVs:
sys.dm_tran_locks:当前锁信息sys.dm_os_wait_stats:等待统计信息
监控查询示例:
sql
-- 查询当前锁信息
SELECT
resource_type,
resource_database_id,
OBJECT_NAME(resource_associated_entity_id) AS object_name,
request_mode,
request_status,
request_session_id,
blocking_session_id
FROM sys.dm_tran_locks
WHERE resource_database_id = DB_ID();阻塞监控
主要 DMVs:
sys.dm_exec_requests:当前请求信息sys.dm_exec_sessions:会话信息sys.dm_os_waiting_tasks:等待任务信息
监控查询示例:
sql
-- 查询阻塞信息
SELECT
w.session_id AS waiting_session_id,
r.blocking_session_id,
DB_NAME(r.database_id) AS database_name,
OBJECT_NAME(r.wait_resource) AS object_name,
w.wait_type,
w.wait_duration_ms / 1000.0 AS wait_duration_seconds,
r.status,
r.command,
SUBSTRING(st.text, (r.statement_start_offset/2)+1,
((CASE r.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE r.statement_end_offset
END - r.statement_start_offset)/2) + 1) AS query_text
FROM sys.dm_os_waiting_tasks w
INNER JOIN sys.dm_exec_requests r ON w.session_id = r.session_id
INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) st
WHERE r.blocking_session_id > 0
ORDER BY wait_duration_ms DESC;死锁监控
主要 DMVs:
sys.dm_os_ring_buffers:包含死锁信息sys.dm_tran_locks:锁信息
监控查询示例:
sql
-- 查询最近的死锁信息
SELECT
CONVERT(xml, event_data).value('(/event/data/value/deadlock)[1]', 'varchar(max)') AS deadlock_graph
FROM sys.fn_xe_file_target_read_file('system_health*.xel', NULL, NULL, NULL)
WHERE object_name = 'xml_deadlock_report';存储相关 DMVs
数据库文件监控
主要 DMVs:
sys.dm_io_virtual_file_stats:文件 I/O 统计信息sys.database_files:数据库文件信息sys.master_files:主数据库文件信息
监控查询示例:
sql
-- 查询数据库文件大小和使用情况
SELECT
DB_NAME(database_id) AS database_name,
name AS file_name,
type_desc AS file_type,
size * 8 / 1024.0 AS total_size_mb,
FILEPROPERTY(name, 'SpaceUsed') * 8 / 1024.0 AS used_size_mb,
(size * 8 / 1024.0) - (FILEPROPERTY(name, 'SpaceUsed') * 8 / 1024.0) AS free_space_mb
FROM sys.database_files;TempDB 监控
主要 DMVs:
sys.dm_db_file_space_usage:TempDB 文件空间使用情况sys.dm_db_task_space_usage:任务空间使用情况sys.dm_db_session_space_usage:会话空间使用情况
监控查询示例:
sql
-- 查询 TempDB 使用情况
SELECT
SUM(unallocated_extent_page_count) * 8 / 1024.0 AS free_space_mb,
SUM(version_store_reserved_page_count) * 8 / 1024.0 AS version_store_mb,
SUM(user_object_reserved_page_count) * 8 / 1024.0 AS user_objects_mb,
SUM(internal_object_reserved_page_count) * 8 / 1024.0 AS internal_objects_mb,
SUM(mixed_extent_page_count) * 8 / 1024.0 AS mixed_extents_mb
FROM sys.dm_db_file_space_usage;
-- 查询 TempDB 中使用空间最多的会话
SELECT
s.session_id,
s.login_name,
s.host_name,
s.program_name,
(tsu.user_objects_alloc_page_count + tsu.internal_objects_alloc_page_count) * 8 / 1024.0 AS tempdb_mb
FROM sys.dm_db_session_space_usage tsu
INNER JOIN sys.dm_exec_sessions s ON tsu.session_id = s.session_id
WHERE tsu.user_objects_alloc_page_count + tsu.internal_objects_alloc_page_count > 0
ORDER BY tempdb_mb DESC;高可用相关 DMVs
Always On 监控
主要 DMVs:
sys.dm_hadr_availability_group_states:可用性组状态sys.dm_hadr_availability_replica_states:副本状态sys.dm_hadr_database_replica_states:数据库副本状态
监控查询示例:
sql
-- 查询 Always On 可用性组状态
SELECT
ag.name AS availability_group_name,
ags.primary_replica,
ags.primary_recovery_health_desc,
ags.synchronization_health_desc
FROM sys.dm_hadr_availability_group_states ags
INNER JOIN sys.availability_groups ag ON ags.group_id = ag.group_id;
-- 查询数据库副本同步状态
SELECT
DB_NAME(drs.database_id) AS database_name,
ar.replica_server_name,
drs.synchronization_state_desc,
drs.synchronization_health_desc,
drs.last_hardened_lsn,
drs.last_redone_lsn,
drs.redo_queue_size,
drs.log_send_queue_size
FROM sys.dm_hadr_database_replica_states drs
INNER JOIN sys.availability_replicas ar ON drs.replica_id = ar.replica_id
ORDER BY database_name, replica_server_name;系统视图
数据库信息视图
主要视图:
sys.databases:数据库信息sys.database_files:数据库文件信息sys.master_files:主数据库文件信息
查询示例:
sql
-- 查询所有数据库信息
SELECT
name,
database_id,
create_date,
state_desc,
recovery_model_desc,
collation_name,
compatibility_level
FROM sys.databases;表信息视图
主要视图:
sys.tables:表信息sys.columns:列信息sys.indexes:索引信息sys.foreign_keys:外键信息
查询示例:
sql
-- 查询表和列信息
SELECT
t.name AS table_name,
c.name AS column_name,
ty.name AS data_type,
c.max_length,
c.precision,
c.scale,
c.is_nullable,
c.is_identity
FROM sys.tables t
INNER JOIN sys.columns c ON t.object_id = c.object_id
INNER JOIN sys.types ty ON c.system_type_id = ty.system_type_id
ORDER BY t.name, c.column_id;常用监控查询
查询 CPU 使用率最高的查询
sql
SELECT
TOP 10
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 query_text,
qs.execution_count,
qs.total_worker_time / 1000000.0 AS total_cpu_seconds,
qs.total_worker_time / qs.execution_count / 1000000.0 AS avg_cpu_seconds,
qs.total_logical_reads,
qs.total_logical_writes
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY total_cpu_seconds DESC;查询内存使用情况
sql
SELECT
type,
name,
SUM(pages_kb) / 1024.0 AS memory_mb
FROM sys.dm_os_memory_clerks
GROUP BY type, name
ORDER BY memory_mb DESC;查询 I/O 等待
sql
SELECT
wait_type,
wait_time_ms / 1000.0 AS wait_time_seconds,
waiting_tasks_count
FROM sys.dm_os_wait_stats
WHERE wait_type LIKE 'PAGEIOLATCH%' OR wait_type LIKE 'WRITELOG'
ORDER BY wait_time_seconds DESC;查询锁和阻塞
sql
SELECT
w.session_id AS waiting_session_id,
r.blocking_session_id,
DB_NAME(r.database_id) AS database_name,
OBJECT_NAME(r.wait_resource) AS object_name,
w.wait_type,
w.wait_duration_ms / 1000.0 AS wait_duration_seconds,
r.status,
r.command,
SUBSTRING(st.text, (r.statement_start_offset/2)+1,
((CASE r.statement_end_offset
WHEN -1 THEN DATALENGTH(st.text)
ELSE r.statement_end_offset
END - r.statement_start_offset)/2) + 1) AS query_text
FROM sys.dm_os_waiting_tasks w
INNER JOIN sys.dm_exec_requests r ON w.session_id = r.session_id
INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) st
WHERE r.blocking_session_id > 0
ORDER BY wait_duration_ms DESC;监控视图最佳实践
定期监控
- 建立监控计划:制定定期监控计划,包括日常监控、周度监控和月度监控
- 监控关键指标:重点监控 CPU、内存、I/O、查询性能和并发情况
- 记录监控数据:将监控数据存储到专门的监控数据库,便于历史分析和趋势预测
- 设置告警阈值:根据性能基线设置合理的告警阈值,及时发现问题
建立性能基线
- 收集基准数据:在系统正常运行时收集性能数据,建立性能基线
- 定期更新基线:随着业务增长和系统变化,定期更新性能基线
- 比较分析:将当前性能数据与基线进行比较,识别异常变化
- 预测趋势:通过历史数据预测性能趋势,提前规划资源扩容
监控工具集成
- 使用 SSMS 监控工具:利用 SSMS 内置的活动监视器、执行计划分析等工具
- 使用 Azure Data Studio:对于 Azure SQL Database 或混合环境,使用 Azure Data Studio
- 使用第三方监控工具:考虑使用 SolarWinds、Redgate SQL Monitor 等第三方工具
- 使用 Azure Monitor:对于 Azure SQL 服务,使用 Azure Monitor 进行监控
权限管理
- 最小权限原则:仅授予必要的 DMV 访问权限
- 使用角色管理:创建专门的监控角色,统一管理监控权限
- 定期审计权限:定期审计 DMV 访问权限,移除不必要的权限
- 使用证书验证:对于远程监控,使用证书验证确保安全访问
版本差异
SQL Server 2012+ 新特性
新增 DMVs:
sys.dm_exec_query_stats:增强了查询统计信息sys.dm_db_missing_index_details:新增缺失索引相关 DMVssys.dm_hadr_availability_group_states:Always On 相关 DMVs
增强现有 DMVs:
sys.dm_os_performance_counters:新增了更多性能计数器sys.dm_tran_locks:增强了锁信息的详细程度
SQL Server 2016+ 新特性
- Query Store:新增查询存储功能,可追踪查询性能变化
- 动态数据掩码:新增数据掩码相关 DMVs
- Always Encrypted:新增加密相关 DMVs
- JSON 支持:新增 JSON 相关函数和 DMVs
SQL Server 2019+ 新特性
- 智能查询处理:新增智能查询处理相关 DMVs
- 内存优化 TempDB 元数据:新增 TempDB 优化相关 DMVs
- 加速数据库恢复:新增加速恢复相关 DMVs
- UTF-8 支持:新增 UTF-8 相关 DMVs
常见问题 (FAQ)
Q: 如何使用 DMVs 监控 SQL Server 性能?
A: 使用 DMVs 监控 SQL Server 性能的步骤:
- 确定需要监控的性能指标(CPU、内存、I/O 等)
- 选择相关的 DMVs(如
sys.dm_os_performance_counters、sys.dm_exec_query_stats等) - 编写监控查询,获取所需信息
- 定期执行查询,收集性能数据
- 分析数据,识别性能瓶颈
- 采取相应的优化措施
Q: 哪些 DMVs 最常用?
A: 最常用的 DMVs 包括:
sys.dm_exec_query_stats:查询性能统计sys.dm_os_performance_counters:性能计数器sys.dm_os_wait_stats:等待统计信息sys.dm_exec_requests:当前请求信息sys.dm_tran_locks:锁信息sys.dm_db_index_usage_stats:索引使用情况
Q: 如何监控慢查询?
A: 监控慢查询的方法:
- 使用
sys.dm_exec_query_statsDMV 查询执行时间长的查询 - 启用 SQL Server Profiler 或 Extended Events 捕获慢查询
- 对于 SQL Server 2016+,使用 Query Store 追踪查询性能变化
- 设置慢查询阈值,通过监控工具进行告警
Q: 如何监控锁和阻塞?
A: 监控锁和阻塞的方法:
- 使用
sys.dm_tran_locks查询当前锁信息 - 使用
sys.dm_exec_requests和sys.dm_os_waiting_tasks查询阻塞信息 - 启用阻塞进程报告,自动捕获阻塞事件
- 使用扩展事件捕获死锁信息
Q: 如何监控 TempDB 使用情况?
A: 监控 TempDB 使用情况的方法:
- 使用
sys.dm_db_file_space_usage查询 TempDB 总体使用情况 - 使用
sys.dm_db_session_space_usage查询会话级别的 TempDB 使用 - 使用
sys.dm_db_task_space_usage查询任务级别的 TempDB 使用 - 监控 TempDB 文件的 I/O 性能,使用
sys.dm_io_virtual_file_stats
Q: 如何监控 Always On 可用性组?
A: 监控 Always On 可用性组的方法:
- 使用
sys.dm_hadr_availability_group_states查询可用性组状态 - 使用
sys.dm_hadr_database_replica_states查询数据库副本同步状态 - 监控副本之间的延迟和同步健康状况
- 设置告警,当同步状态异常时及时通知
Q: DMVs 查询会影响数据库性能吗?
A: 某些 DMVs 查询可能会对性能产生影响,特别是在高负载环境下。建议:
- 避免频繁执行复杂的 DMV 查询
- 限制查询返回的行数,使用 TOP 子句
- 在非高峰期执行密集的 DMV 查询
- 考虑使用采样方式收集数据
Q: 如何获取历史性能数据?
A: 获取历史性能数据的方法:
- 定期将 DMV 查询结果存储到专门的监控数据库
- 使用 SQL Server Profiler 或 Extended Events 捕获历史事件
- 对于 SQL Server 2016+,使用 Query Store 追踪查询性能变化
- 使用 Azure Monitor 或第三方监控工具收集历史数据
总结
SQLServer 监控视图是数据库性能监控和故障诊断的重要工具,通过合理使用 DMVs 和系统视图,可以全面了解数据库的运行状态,识别性能瓶颈,解决并发问题,确保数据库的高可用性和安全性。
在实际生产环境中,应结合使用多种监控方法,包括 DMVs 查询、系统视图、SQL Server Profiler、Extended Events 和第三方监控工具,建立完善的监控体系。同时,应定期收集性能数据,建立性能基线,便于比较和分析性能变化,提前发现和解决潜在问题。
随着 SQLServer 版本的不断更新,监控视图的功能也在不断增强,开发人员和数据库管理员应持续学习和掌握新的监控特性,提高监控效率和准确性。
