外观
SQLServer 动态管理视图与函数
SQLServer动态管理视图(Dynamic Management Views, DMV)和动态管理函数(Dynamic Management Functions, DMF)是一组用于监控SQLServer实例和数据库性能、状态的系统视图和函数。它们提供了丰富的实时性能数据,帮助DBA诊断和解决性能问题。
动态管理对象概述
1. 什么是动态管理对象
动态管理对象(Dynamic Management Objects, DMO)是SQLServer提供的一组系统视图和函数,用于:
- 监控服务器实例的健康状态
- 诊断性能问题
- 调优查询和索引
- 监控资源使用情况
- 分析等待统计信息
2. 动态管理对象的分类
根据访问权限和监控范围,动态管理对象可以分为以下几类:
| 分类 | 前缀 | 访问权限 | 监控范围 |
|---|---|---|---|
| 服务器范围的DMV/DMF | sys.dm_os_* | VIEW SERVER STATE | 服务器级别的资源和性能 |
| 数据库范围的DMV/DMF | sys.dm_db_* | VIEW DATABASE STATE | 数据库级别的资源和性能 |
| 执行相关的DMV/DMF | sys.dm_exec_* | VIEW SERVER STATE | 查询执行、连接和会话 |
| 事务相关的DMV/DMF | sys.dm_tran_* | VIEW SERVER STATE | 事务、锁和隔离级别 |
| I/O相关的DMV/DMF | sys.dm_io_* | VIEW SERVER STATE | 磁盘I/O和文件系统 |
| 全文搜索相关的DMV/DMF | sys.dm_fts_* | VIEW SERVER STATE | 全文搜索性能 |
| Service Broker相关的DMV/DMF | sys.dm_broker_* | VIEW SERVER STATE | Service Broker性能 |
3. 访问权限要求
- 服务器范围的DMV/DMF:需要
VIEW SERVER STATE权限 - 数据库范围的DMV/DMF:需要
VIEW DATABASE STATE权限
可以使用以下T-SQL命令授予这些权限:
sql
-- 授予VIEW SERVER STATE权限
GRANT VIEW SERVER STATE TO [YourLogin];
-- 授予VIEW DATABASE STATE权限
GRANT VIEW DATABASE STATE TO [YourUser];常用动态管理视图与函数
1. 服务器资源监控
sys.dm_os_performance_counters
用途:返回SQLServer性能计数器的当前值
常用指标:
- Buffer cache hit ratio:缓冲区缓存命中率
- Page life expectancy:页寿命
- Batch requests/sec:每秒批处理请求数
- SQL Server:General Statistics - User Connections:当前用户连接数
查询示例:
sql
-- 查询关键性能计数器
SELECT
object_name,
counter_name,
cntr_value,
cntr_type
FROM
sys.dm_os_performance_counters
WHERE
counter_name IN ('Buffer cache hit ratio', 'Page life expectancy', 'Batch requests/sec', 'User Connections')
ORDER BY
object_name, counter_name;sys.dm_os_memory_clerks
用途:返回SQLServer内存分配器的内存使用情况
常用字段:
- type:内存分配器类型
- name:内存分配器名称
- single_pages_kb:单页分配的内存(KB)
- multi_pages_kb:多页分配的内存(KB)
- virtual_memory_committed_kb:已提交的虚拟内存(KB)
查询示例:
sql
-- 查询内存使用情况
SELECT
type,
name,
(single_pages_kb + multi_pages_kb + virtual_memory_committed_kb) / 1024.0 AS total_memory_mb
FROM
sys.dm_os_memory_clerks
ORDER BY
total_memory_mb DESC;sys.dm_os_schedulers
用途:返回SQLServer调度器的信息
常用字段:
- scheduler_id:调度器ID
- cpu_id:CPU ID
- status:调度器状态
- current_tasks_count:当前任务数
- runnable_tasks_count:可运行任务数
- current_workers_count:当前工作线程数
查询示例:
sql
-- 查询调度器状态
SELECT
scheduler_id,
cpu_id,
status,
current_tasks_count,
runnable_tasks_count,
current_workers_count
FROM
sys.dm_os_schedulers
WHERE
status = 'VISIBLE ONLINE';2. 查询性能监控
sys.dm_exec_query_stats
用途:返回查询执行的统计信息
常用字段:
- sql_handle:SQL语句句柄
- plan_handle:执行计划句柄
- execution_count:执行次数
- total_worker_time:总CPU时间
- total_elapsed_time:总执行时间
- total_logical_reads:总逻辑读取次数
- total_logical_writes:总逻辑写入次数
- total_physical_reads:总物理读取次数
查询示例:
sql
-- 查询前10个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 statement_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_elapsed_time / 1000000.0 AS total_elapsed_seconds,
qs.total_elapsed_time / qs.execution_count / 1000000.0 AS avg_elapsed_seconds
FROM
sys.dm_exec_query_stats AS qs
CROSS APPLY
sys.dm_exec_sql_text(qs.sql_handle) AS st
ORDER BY
total_cpu_seconds DESC;sys.dm_exec_requests
用途:返回当前执行的请求信息
常用字段:
- session_id:会话ID
- request_id:请求ID
- start_time:请求开始时间
- status:请求状态
- command:命令类型
- wait_type:等待类型
- wait_time:等待时间
- last_wait_type:最后等待类型
- wait_resource:等待资源
- cpu_time:CPU时间
- logical_reads:逻辑读取次数
- reads:物理读取次数
- writes:写入次数
- text_size:文本大小
- language:语言
- query_hash:查询哈希值
查询示例:
sql
-- 查询当前活跃请求
SELECT
session_id,
status,
command,
wait_type,
wait_time,
cpu_time,
logical_reads,
reads,
writes,
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 statement_text
FROM
sys.dm_exec_requests AS r
CROSS APPLY
sys.dm_exec_sql_text(r.sql_handle) AS st
WHERE
session_id > 50;sys.dm_exec_sessions
用途:返回所有活动会话的信息
常用字段:
- session_id:会话ID
- login_time:登录时间
- host_name:主机名
- program_name:程序名
- login_name:登录名
- status:会话状态
- cpu_time:CPU时间
- logical_reads:逻辑读取次数
- reads:物理读取次数
- writes:写入次数
- last_request_start_time:最后请求开始时间
- last_request_end_time:最后请求结束时间
查询示例:
sql
-- 查询活跃会话
SELECT
session_id,
login_time,
host_name,
program_name,
login_name,
status,
cpu_time,
logical_reads,
reads,
writes,
last_request_start_time
FROM
sys.dm_exec_sessions
WHERE
status = 'running' AND session_id > 50;3. 索引和表性能
sys.dm_db_index_usage_stats
用途:返回索引使用情况统计信息
常用字段:
- database_id:数据库ID
- object_id:对象ID
- index_id:索引ID
- user_seeks:用户查找次数
- user_scans:用户扫描次数
- user_lookups:用户查找次数
- user_updates:用户更新次数
- last_user_seek:最后用户查找时间
- last_user_scan:最后用户扫描时间
- last_user_lookup:最后用户查找时间
- last_user_update:最后用户更新时间
查询示例:
sql
-- 查询未使用的索引
SELECT
DB_NAME(database_id) AS database_name,
OBJECT_NAME(object_id, database_id) AS table_name,
i.name AS index_name,
iu.user_seeks,
iu.user_scans,
iu.user_lookups,
iu.user_updates,
iu.last_user_seek,
iu.last_user_scan
FROM
sys.dm_db_index_usage_stats AS iu
JOIN
sys.indexes AS i ON iu.object_id = i.object_id AND iu.index_id = i.index_id
WHERE
iu.database_id = DB_ID()
AND iu.user_seeks = 0
AND iu.user_scans = 0
AND iu.user_lookups = 0
AND i.index_id > 0
AND i.is_primary_key = 0
AND i.is_unique_constraint = 0;sys.dm_db_index_physical_stats
用途:返回索引物理状态信息
常用字段:
- database_id:数据库ID
- object_id:对象ID
- index_id:索引ID
- partition_number:分区号
- index_type_desc:索引类型描述
- alloc_unit_type_desc:分配单元类型描述
- avg_fragmentation_in_percent:平均碎片百分比
- fragment_count:碎片数量
- avg_fragment_size_in_pages:平均碎片大小(页数)
- page_count:页数
查询示例:
sql
-- 查询索引碎片率
SELECT
DB_NAME(database_id) AS database_name,
OBJECT_NAME(object_id, database_id) AS table_name,
i.name AS index_name,
ips.avg_fragmentation_in_percent,
ips.fragment_count,
ips.page_count
FROM
sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'LIMITED') AS ips
JOIN
sys.indexes AS i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE
ips.avg_fragmentation_in_percent > 10
AND ips.page_count > 1000
ORDER BY
ips.avg_fragmentation_in_percent DESC;sys.dm_db_missing_index_details
用途:返回缺失索引的详细信息
常用字段:
- index_handle:索引句柄
- database_id:数据库ID
- object_id:对象ID
- equality_columns:等值列
- inequality_columns:非等值列
- included_columns:包含列
查询示例:
sql
-- 查询缺失索引
SELECT
DB_NAME(database_id) AS database_name,
OBJECT_NAME(object_id, database_id) AS table_name,
equality_columns,
inequality_columns,
included_columns,
statement AS create_index_statement
FROM
sys.dm_db_missing_index_details
WHERE
database_id = DB_ID();4. 等待统计信息
sys.dm_os_wait_stats
用途:返回等待类型的统计信息
常用字段:
- wait_type:等待类型
- waiting_tasks_count:等待任务数
- wait_time_ms:总等待时间(毫秒)
- max_wait_time_ms:最大等待时间(毫秒)
- signal_wait_time_ms:信号等待时间(毫秒)
查询示例:
sql
-- 查询主要等待类型
SELECT TOP 10
wait_type,
wait_time_ms,
(wait_time_ms * 100.0) / SUM(wait_time_ms) OVER () AS wait_time_percent,
waiting_tasks_count,
max_wait_time_ms,
signal_wait_time_ms
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', 'XE_DISPATCHER_JOIN')
ORDER BY
wait_time_ms DESC;5. 数据库状态监控
sys.dm_db_file_space_usage
用途:返回数据库文件空间使用情况
常用字段:
- database_id:数据库ID
- file_id:文件ID
- filegroup_id:文件组ID
- total_page_count:总页数
- allocated_extent_page_count:已分配扩展区页数
- unallocated_extent_page_count:未分配扩展区页数
查询示例:
sql
-- 查询数据库文件空间使用情况
SELECT
DB_NAME(database_id) AS database_name,
name AS file_name,
type_desc,
(total_page_count * 8.0) / 1024.0 AS total_size_mb,
(allocated_extent_page_count * 8.0) / 1024.0 AS used_size_mb,
(unallocated_extent_page_count * 8.0) / 1024.0 AS free_size_mb,
(allocated_extent_page_count * 100.0) / total_page_count AS used_percent
FROM
sys.dm_db_file_space_usage
JOIN
sys.master_files AS mf ON dmfs.database_id = mf.database_id AND dmfs.file_id = mf.file_id
WHERE
database_id = DB_ID();sys.dm_db_log_space_usage
用途:返回事务日志空间使用情况
常用字段:
- database_id:数据库ID
- total_log_size_in_bytes:总日志大小(字节)
- used_log_space_in_bytes:已使用日志大小(字节)
- used_log_space_in_percent:已使用日志百分比
- log_space_in_bytes_since_last_backup:上次备份以来的日志大小(字节)
查询示例:
sql
-- 查询事务日志空间使用情况
SELECT
DB_NAME(database_id) AS database_name,
total_log_size_in_bytes / 1024 / 1024 AS total_log_size_mb,
used_log_space_in_bytes / 1024 / 1024 AS used_log_size_mb,
used_log_space_in_percent,
log_space_in_bytes_since_last_backup / 1024 / 1024 AS log_space_since_last_backup_mb
FROM
sys.dm_db_log_space_usage;6. I/O性能监控
sys.dm_io_virtual_file_stats
用途:返回数据库文件I/O统计信息
常用字段:
- database_id:数据库ID
- file_id:文件ID
- sample_ms:采样时间(毫秒)
- num_of_reads:读取次数
- num_of_writes:写入次数
- io_stall_read_ms:读取等待时间(毫秒)
- io_stall_write_ms:写入等待时间(毫秒)
- io_stall:总I/O等待时间(毫秒)
- size_on_disk_bytes:磁盘上的大小(字节)
查询示例:
sql
-- 查询数据库文件I/O延迟
SELECT
DB_NAME(database_id) AS database_name,
mf.name AS file_name,
mf.type_desc,
num_of_reads,
num_of_writes,
io_stall_read_ms,
io_stall_write_ms,
io_stall_read_ms / NULLIF(num_of_reads, 0) AS avg_read_latency_ms,
io_stall_write_ms / NULLIF(num_of_writes, 0) AS avg_write_latency_ms
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
WHERE
vfs.database_id = DB_ID()
ORDER BY
avg_read_latency_ms DESC, avg_write_latency_ms DESC;DMV/DMF在性能诊断中的应用
1. 性能瓶颈诊断
步骤:
- 检查CPU使用率:使用sys.dm_os_performance_counters和sys.dm_exec_query_stats
- 检查内存使用情况:使用sys.dm_os_memory_clerks和sys.dm_os_performance_counters
- 检查磁盘I/O:使用sys.dm_io_virtual_file_stats和sys.dm_os_wait_stats
- 检查查询性能:使用sys.dm_exec_query_stats和sys.dm_exec_requests
- 检查等待统计信息:使用sys.dm_os_wait_stats
示例脚本:
sql
-- 性能诊断综合脚本
-- 1. CPU使用率
SELECT
(total_worker_time - start_time_total_worker_time) / 1000000.0 AS cpu_usage_seconds
FROM
(SELECT
SUM(ws.total_worker_time) AS total_worker_time,
MIN(ws.start_time_total_worker_time) AS start_time_total_worker_time
FROM
(SELECT
SUM(worker_time) OVER () AS total_worker_time,
MIN(start_time) OVER () AS start_time_total_worker_time
FROM
sys.dm_exec_requests
WHERE
session_id > 50) AS ws) AS t;
-- 2. 内存使用情况
SELECT
(SELECT cntr_value FROM sys.dm_os_performance_counters WHERE counter_name = 'Page life expectancy') AS page_life_expectancy,
(SELECT cntr_value FROM sys.dm_os_performance_counters WHERE counter_name = 'Buffer cache hit ratio') * 1.0 /
(SELECT cntr_value FROM sys.dm_os_performance_counters WHERE counter_name = 'Buffer cache hit ratio base') * 100 AS buffer_cache_hit_ratio_percent;
-- 3. 磁盘I/O
SELECT TOP 5
DB_NAME(database_id) AS database_name,
mf.name AS file_name,
mf.type_desc,
io_stall_read_ms / NULLIF(num_of_reads, 0) AS avg_read_latency_ms,
io_stall_write_ms / NULLIF(num_of_writes, 0) AS avg_write_latency_ms
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
io_stall_read_ms + io_stall_write_ms DESC;
-- 4. 主要等待类型
SELECT TOP 5
wait_type,
wait_time_ms,
(wait_time_ms * 100.0) / SUM(wait_time_ms) OVER () AS wait_time_percent
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', 'XE_DISPATCHER_JOIN')
ORDER BY
wait_time_ms DESC;
-- 5. 活跃请求
SELECT TOP 5
session_id,
status,
command,
wait_type,
wait_time,
cpu_time,
logical_reads,
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 statement_text
FROM
sys.dm_exec_requests AS r
CROSS APPLY
sys.dm_exec_sql_text(r.sql_handle) AS st
WHERE
session_id > 50
ORDER BY
cpu_time DESC;2. 长时间运行的查询监控
示例脚本:
sql
-- 监控长时间运行的查询
SELECT
session_id,
status,
command,
DATEDIFF(second, start_time, GETDATE()) AS running_seconds,
cpu_time / 1000 AS cpu_seconds,
logical_reads,
reads,
writes,
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 statement_text
FROM
sys.dm_exec_requests AS r
CROSS APPLY
sys.dm_exec_sql_text(r.sql_handle) AS st
WHERE
session_id > 50
AND DATEDIFF(second, start_time, GETDATE()) > 60 -- 运行时间超过60秒
ORDER BY
running_seconds DESC;3. 死锁监控
示例脚本:
sql
-- 监控死锁信息
SELECT
CAST(xe.event_data AS XML).value('(event/@timestamp)[1]', 'datetime2(3)') AS event_time,
CAST(xe.event_data AS XML).value('(event/data[@name="deadlock_graph"]/value)[1]', 'varchar(max)') AS deadlock_graph
FROM
sys.fn_xe_file_target_read_file('system_health*.xel', NULL, NULL, NULL)
AS xe
WHERE
xe.event_data LIKE '%deadlock%';DMV/DMF最佳实践
1. 性能影响考虑
- DMV/DMF查询会消耗系统资源,尤其是在高负载系统上
- 避免在生产系统上执行过于复杂或频繁的DMV/DMF查询
- 考虑将DMV/DMF数据收集到专用监控数据库中
2. 数据准确性
- DMV/DMF数据在SQLServer服务重启后会重置
- 某些DMV/DMF数据可能会延迟更新
- 对于历史趋势分析,应定期收集和存储DMV/DMF数据
3. 权限管理
- 严格控制DMV/DMF的访问权限
- 只授予必要的权限
- 考虑使用存储过程封装DMV/DMF查询,限制返回结果
4. 版本兼容性
- 不同SQLServer版本的DMV/DMF可能存在差异
- 在升级SQLServer版本前,测试DMV/DMF查询
- 参考官方文档确认DMV/DMF的版本支持情况
5. 结合其他监控工具
- 将DMV/DMF与其他监控工具结合使用
- 利用Query Store和Extended Events增强监控能力
- 考虑使用第三方监控工具自动收集和分析DMV/DMF数据
版本差异
| SQLServer版本 | DMV/DMF特性 |
|---|---|
| 2005 | 引入基本DMV/DMF,包括sys.dm_exec_query_stats, sys.dm_os_wait_stats等 |
| 2008/2008R2 | 增强DMV/DMF功能,添加sys.dm_db_partition_stats, sys.dm_db_index_physical_stats等 |
| 2012 | 新增Columnstore索引相关DMV/DMF,增强内存优化表监控 |
| 2014 | 新增内存优化表相关DMV/DMF,增强查询存储支持 |
| 2016 | 新增Query Store相关DMV/DMF,增强JSON支持 |
| 2017 | 新增图形数据库相关DMV/DMF,增强智能查询处理监控 |
| 2019 | 新增Intelligent Query Processing相关DMV/DMF,增强加速数据库恢复(ADR)监控 |
| Azure SQL DB | 支持大部分DMV/DMF,新增Azure特有DMV/DMF |
常见问题(FAQ)
Q1: DMV/DMF数据在SQLServer重启后会丢失吗?
A: 是的,大部分DMV/DMF数据在SQLServer服务重启后会重置。因此,对于历史趋势分析,建议定期收集和存储DMV/DMF数据。
Q2: DMV/DMF查询会影响系统性能吗?
A: 是的,DMV/DMF查询会消耗一定的系统资源,尤其是在高负载系统上。建议避免在生产系统上执行过于复杂或频繁的DMV/DMF查询。
Q3: 如何获取历史DMV/DMF数据?
A: 可以通过以下方法获取历史DMV/DMF数据:
- 定期运行DMV/DMF查询,将结果存储到专用监控数据库中
- 使用SQL Server代理作业自动收集DMV/DMF数据
- 使用第三方监控工具自动收集和分析DMV/DMF数据
Q4: 如何确定哪些DMV/DMF对性能诊断最有用?
A: 最有用的DMV/DMF取决于具体的性能问题:
- CPU问题:sys.dm_exec_query_stats, sys.dm_os_performance_counters
- 内存问题:sys.dm_os_memory_clerks, sys.dm_os_performance_counters
- I/O问题:sys.dm_io_virtual_file_stats, sys.dm_os_wait_stats
- 查询性能问题:sys.dm_exec_query_stats, sys.dm_exec_requests
- 索引问题:sys.dm_db_index_usage_stats, sys.dm_db_missing_index_details
Q5: DMV/DMF和性能计数器有什么区别?
A: DMV/DMF和性能计数器都是用于监控SQLServer性能的工具,但它们有以下区别:
- DMV/DMF提供更详细的内部系统状态信息
- 性能计数器更易于使用,提供标准化的性能指标
- DMV/DMF支持更复杂的查询和分析
- 性能计数器更适合实时监控和告警
Q6: 如何使用DMV/DMF诊断死锁问题?
A: 可以使用以下DMV/DMF诊断死锁问题:
- sys.dm_os_wait_stats:查找死锁相关的等待类型(如LCK_M_*)
- sys.dm_tran_locks:查看当前锁信息
- sys.dm_tran_active_transactions:查看当前活跃事务
- system_health扩展事件会话:查看历史死锁信息
总结
SQLServer动态管理视图(DMV)和动态管理函数(DMF)是强大的性能监控和诊断工具,提供了丰富的实时系统状态信息。通过合理使用DMV/DMF,可以帮助DBA快速定位和解决性能问题,优化数据库性能,确保系统稳定运行。
在使用DMV/DMF时,需要注意:
- 考虑性能影响,避免在生产系统上执行过于复杂或频繁的查询
- 严格控制访问权限,只授予必要的权限
- 定期收集和存储DMV/DMF数据,用于历史趋势分析
- 结合其他监控工具,增强监控能力
- 注意不同SQLServer版本的DMV/DMF差异
通过掌握DMV/DMF的使用方法和最佳实践,可以提高SQLServer数据库的性能管理水平,确保业务系统的高效运行。
