Microsoft SQL Server 2005 提供了一些工具来监控数据库。方法之一是动态管理视图。动态管理视图 (DMV) 和动态管理函数 (DMF) 返回的服务器状态信息可用于监控服务器实例的运行状况、诊断问题和优化性能。
常规服务器动态管理对象包括:
此部分介绍为监控 SQL Server 运行状况而针对这些动态管理视图和函数运行的一些常用查询。
您可以运行以下查询来获取所有 DMV 和 DMF 名称:
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">SELECT</span><span> * </span><span class="keyword">FROM</span><span> sys.system_objects </span></span></li><li><span><span class="keyword">WHERE</span><span> </span><span class="keyword">name</span><span> </span><span class="op">LIKE</span><span> </span><span class="string">'dm_%'</span><span> </span></span></li><li class="alt"><span><span class="keyword">ORDER</span><span> </span><span class="keyword">BY</span><span> </span><span class="keyword">name</span><span> </span></span></li></ol> |
CPU 瓶颈通常由以下原因引起:查询计划并非最优、配置不当、设计因素不良或硬件资源不足。下面的常用查询可帮助您确定导致 CPU 瓶颈的原因。
下面的查询使您能够深入了解当前缓存的哪些批处理或过程占用了大部分 CPU 资源。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">SELECT</span><span> </span><span class="keyword">TOP</span><span> 50 </span></span></li><li><span> <span class="func">SUM</span><span>(qs.total_worker_time) </span><span class="keyword">AS</span><span> total_cpu_time, </span></span></li><li class="alt"><span> <span class="func">SUM</span><span>(qs.execution_count) </span><span class="keyword">AS</span><span> total_execution_count, </span></span></li><li><span> <span class="func">COUNT</span><span>(*) </span><span class="keyword">AS</span><span> number_of_statements, </span></span></li><li class="alt"><span> qs.sql_handle </span></li><li><span><span class="keyword">FROM</span><span> sys.dm_exec_query_stats </span><span class="keyword">AS</span><span> qs </span></span></li><li class="alt"><span><span class="keyword">GROUP</span><span> </span><span class="keyword">BY</span><span> qs.sql_handle </span></span></li><li><span><span class="keyword">ORDER</span><span> </span><span class="keyword">BY</span><span> </span><span class="func">SUM</span><span>(qs.total_worker_time) </span><span class="keyword">DESC</span><span> </span></span></li></ol> |
下面的查询显示缓存计划所占用的 CPU 总使用率(带 SQL 文本)。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">SELECT</span><span> </span></span></li><li><span> total_cpu_time, </span></li><li class="alt"><span> total_execution_count, </span></li><li><span> number_of_statements, </span></li><li class="alt"><span> s2.text </span></li><li><span> <span class="comment">--(SELECT SUBSTRING(s2.text, statement_start_offset / 2, ((CASE WHEN statement_end_offset = -1 THEN (LEN(CONVERT(NVARCHAR(MAX), s2.text)) * 2) ELSE statement_end_offset END) - statement_start_offset) / 2) ) AS query_text</span><span> </span></span></li><li class="alt"><span><span class="keyword">FROM</span><span> </span></span></li><li><span> (<span class="keyword">SELECT</span><span> </span><span class="keyword">TOP</span><span> 50 </span></span></li><li class="alt"><span> <span class="func">SUM</span><span>(qs.total_worker_time) </span><span class="keyword">AS</span><span> total_cpu_time, </span></span></li><li><span> <span class="func">SUM</span><span>(qs.execution_count) </span><span class="keyword">AS</span><span> total_execution_count, </span></span></li><li class="alt"><span> <span class="func">COUNT</span><span>(*) </span><span class="keyword">AS</span><span> number_of_statements, </span></span></li><li><span> qs.sql_handle <span class="comment">--,</span><span> </span></span></li><li class="alt"><span> <span class="comment">--MIN(statement_start_offset) AS statement_start_offset, </span><span> </span></span></li><li><span> <span class="comment">--MAX(statement_end_offset) AS statement_end_offset</span><span> </span></span></li><li class="alt"><span> <span class="keyword">FROM</span><span> </span></span></li><li><span> sys.dm_exec_query_stats <span class="keyword">AS</span><span> qs </span></span></li><li class="alt"><span> <span class="keyword">GROUP</span><span> </span><span class="keyword">BY</span><span> qs.sql_handle </span></span></li><li><span> <span class="keyword">ORDER</span><span> </span><span class="keyword">BY</span><span> </span><span class="func">SUM</span><span>(qs.total_worker_time) </span><span class="keyword">DESC</span><span>) </span><span class="keyword">AS</span><span> stats </span></span></li><li class="alt"><span> <span class="op">CROSS</span><span> APPLY sys.dm_exec_sql_text(stats.sql_handle) </span><span class="keyword">AS</span><span> s2 </span></span></li></ol> |
下面的查询显示 CPU 平均占用率最高的前 50 个 SQL 语句。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">SELECT</span><span> </span><span class="keyword">TOP</span><span> 50 </span></span></li><li><span>total_worker_time/execution_count <span class="keyword">AS</span><span> [</span><span class="func">Avg</span><span> CPU </span><span class="keyword">Time</span><span>], </span></span></li><li class="alt"><span>(<span class="keyword">SELECT</span><span> </span><span class="func">SUBSTRING</span><span>(text,statement_start_offset/2,(</span><span class="func">CASE</span><span> </span><span class="keyword">WHEN</span><span> statement_end_offset = -1 </span><span class="keyword">then</span><span> LEN(</span><span class="func">CONVERT</span><span>(nvarchar(</span><span class="keyword">max</span><span>), text)) * 2 </span><span class="keyword">ELSE</span><span> statement_end_offset </span><span class="keyword">end</span><span> -statement_start_offset)/2) </span><span class="keyword">FROM</span><span> sys.dm_exec_sql_text(sql_handle)) </span><span class="keyword">AS</span><span> query_text, * </span></span></li><li><span><span class="keyword">FROM</span><span> sys.dm_exec_query_stats </span></span></li><li class="alt"><span><span class="keyword">ORDER</span><span> </span><span class="keyword">BY</span><span> [</span><span class="func">Avg</span><span> CPU </span><span class="keyword">Time</span><span>] </span><span class="keyword">DESC</span><span> </span></span></li></ol> |
下面显示用于找出过多编译/重新编译的 DMV 查询。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> * </span><span class="keyword">from</span><span> sys.dm_exec_query_optimizer_info </span></span></li><li><span><span class="keyword">where</span><span> </span></span></li><li class="alt"><span> counter = <span class="string">'optimizations'</span><span> </span></span></li><li><span> <span class="op">or</span><span> counter = </span><span class="string">'elapsed time'</span><span> </span></span></li></ol> |
下面的示例查询显示已重新编译的前 25 个存储过程。plan_generation_num 指示该查询已重新编译的次数。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> </span><span class="keyword">top</span><span> 25 </span></span></li><li><span> sql_text.text, </span></li><li class="alt"><span> sql_handle, </span></li><li><span> plan_generation_num, </span></li><li class="alt"><span> execution_count, </span></li><li><span> dbid, </span></li><li class="alt"><span> objectid </span></li><li><span><span class="keyword">from</span><span> sys.dm_exec_query_stats a </span></span></li><li class="alt"><span> <span class="op">cross</span><span> apply sys.dm_exec_sql_text(sql_handle) </span><span class="keyword">as</span><span> sql_text </span></span></li><li><span><span class="keyword">where</span><span> plan_generation_num > 1 </span></span></li><li class="alt"><span><span class="keyword">order</span><span> </span><span class="keyword">by</span><span> plan_generation_num </span><span class="keyword">desc</span><span> </span></span></li></ol> |
效率较低的查询计划可能增大 CPU 占用率。
下面的查询显示哪个查询占用了最多的 CPU 累计使用率。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">SELECT</span><span> </span></span></li><li><span> highest_cpu_queries.plan_handle, </span></li><li class="alt"><span> highest_cpu_queries.total_worker_time, </span></li><li><span> q.dbid, </span></li><li class="alt"><span> q.objectid, </span></li><li><span> q.number, </span></li><li class="alt"><span> q.encrypted, </span></li><li><span> q.[text] </span></li><li class="alt"><span><span class="keyword">from</span><span> </span></span></li><li><span> (<span class="keyword">select</span><span> </span><span class="keyword">top</span><span> 50 </span></span></li><li class="alt"><span> qs.plan_handle, </span></li><li><span> qs.total_worker_time </span></li><li class="alt"><span> <span class="keyword">from</span><span> </span></span></li><li><span> sys.dm_exec_query_stats qs </span></li><li class="alt"><span> <span class="keyword">order</span><span> </span><span class="keyword">by</span><span> qs.total_worker_time </span><span class="keyword">desc</span><span>) </span><span class="keyword">as</span><span> highest_cpu_queries </span></span></li><li><span> <span class="op">cross</span><span> apply sys.dm_exec_sql_text(plan_handle) </span><span class="keyword">as</span><span> q </span></span></li><li class="alt"><span><span class="keyword">order</span><span> </span><span class="keyword">by</span><span> highest_cpu_queries.total_worker_time </span><span class="keyword">desc</span><span> </span></span></li></ol> |
下面的查询显示一些可能占用大量 CPU 使用率的运算符(例如 ‘%Hash Match%’、‘%Sort%’)以找出可疑对象。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> * </span></span></li><li><span><span class="keyword">from</span><span> </span></span></li><li class="alt"><span> sys.dm_exec_cached_plans </span></li><li><span> <span class="op">cross</span><span> apply sys.dm_exec_query_plan(plan_handle) </span></span></li><li class="alt"><span><span class="keyword">where</span><span> </span></span></li><li><span> <span class="func">cast</span><span>(query_plan </span><span class="keyword">as</span><span> nvarchar(</span><span class="keyword">max</span><span>)) </span><span class="op">like</span><span> </span><span class="string">'%Sort%'</span><span> </span></span></li><li class="alt"><span> <span class="op">or</span><span> </span><span class="func">cast</span><span>(query_plan </span><span class="keyword">as</span><span> nvarchar(</span><span class="keyword">max</span><span>)) </span><span class="op">like</span><span> </span><span class="string">'%Hash Match%'</span><span> </span></span></li></ol> |
如果已检测到效率低下并导致 CPU 占用率较高的查询计划,请对该查询中涉及的表运行 UPDATE STATISTICS 以查看该问题是否仍然存在。然后,收集相关数据并将此问题报告给 PerformancePoint 规划支持人员。
如果您的系统存在过多的编译和重新编译,可能会导致系统出现与 CPU 相关的性能问题。
您可以运行下面的 DMV 查询来找出过多的编译/重新编译。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> * </span><span class="keyword">from</span><span> sys.dm_exec_query_optimizer_info </span></span></li><li><span><span class="keyword">where</span><span> </span></span></li><li class="alt"><span>counter = <span class="string">'optimizations'</span><span> </span></span></li><li><span><span class="op">or</span><span> counter = </span><span class="string">'elapsed time'</span><span> </span></span></li></ol> |
下面的示例查询显示已重新编译的前 25 个存储过程。plan_generation_num 指示该查询已重新编译的次数。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> </span><span class="keyword">top</span><span> 25 </span></span></li><li><span>sql_text.text, </span></li><li class="alt"><span>sql_handle, </span></li><li><span>plan_generation_num, </span></li><li class="alt"><span>execution_count, </span></li><li><span>dbid, </span></li><li class="alt"><span>objectid </span></li><li><span><span class="keyword">from</span><span> sys.dm_exec_query_stats a </span></span></li><li class="alt"><span><span class="op">cross</span><span> apply sys.dm_exec_sql_text(sql_handle) </span><span class="keyword">as</span><span> sql_text </span></span></li><li><span><span class="keyword">where</span><span> plan_generation_num > 1 </span></span></li><li class="alt"><span><span class="keyword">order</span><span> </span><span class="keyword">by</span><span> plan_generation_num </span><span class="keyword">desc</span><span> </span></span></li></ol> |
如果已检测到过多的编译或重新编译,请尽可能多地收集相关数据并将其报告给规划支持人员。
开始内存压力检测和调查之前,请确保已启用 SQL Server 中的高级选项。请先对 master 数据库运行以下查询以启用此选项。
1 |
<ol class="dp-sql"><li class="alt"><span><span>sp_configure </span><span class="string">'show advanced options'</span><span> </span></span></li><li><span>go </span></li><li class="alt"><span>sp_configure <span class="string">'show advanced options'</span><span>, 1 </span></span></li><li><span>go </span></li><li class="alt"><span>reconfigure </span></li><li><span>go </span></li></ol> |
首先运行以下查询以检查内存相关配置选项。
1 |
<ol class="dp-sql"><li class="alt"><span><span>sp_configure </span><span class="string">'awe_enabled'</span><span> </span></span></li><li><span>go </span></li><li class="alt"><span>sp_configure <span class="string">'min server memory'</span><span> </span></span></li><li><span>go </span></li><li class="alt"><span>sp_configure <span class="string">'max server memory'</span><span> </span></span></li><li><span>go </span></li><li class="alt"><span>sp_configure <span class="string">'min memory per query'</span><span> </span></span></li><li><span>go </span></li><li class="alt"><span>sp_configure <span class="string">'query wait'</span><span> </span></span></li><li><span>go </span></li></ol> |
运行下面的 DMV 查询以查看 CPU、计划程序内存和缓冲池信息。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> </span></span></li><li><span>cpu_count, </span></li><li class="alt"><span>hyperthread_ratio, </span></li><li><span>scheduler_count, </span></li><li class="alt"><span>physical_memory_in_bytes / 1024 / 1024 <span class="keyword">as</span><span> physical_memory_mb, </span></span></li><li><span>virtual_memory_in_bytes / 1024 / 1024 <span class="keyword">as</span><span> virtual_memory_mb, </span></span></li><li class="alt"><span>bpool_committed * 8 / 1024 <span class="keyword">as</span><span> bpool_committed_mb, </span></span></li><li><span>bpool_commit_target * 8 / 1024 <span class="keyword">as</span><span> bpool_target_mb, </span></span></li><li class="alt"><span>bpool_visible * 8 / 1024 <span class="keyword">as</span><span> bpool_visible_mb </span></span></li><li><span><span class="keyword">from</span><span> sys.dm_os_sys_info </span></span></li></ol> |
检查闩锁等待统计信息以确定 I/O 瓶颈。运行下面的 DMV 查询以查找 I/O 闩锁等待统计信息。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> wait_type, waiting_tasks_count, wait_time_ms, signal_wait_time_ms, wait_time_ms / waiting_tasks_count </span></span></li><li><span><span class="keyword">from</span><span> sys.dm_os_wait_stats </span></span></li><li class="alt"><span><span class="keyword">where</span><span> wait_type </span><span class="op">like</span><span> </span><span class="string">'PAGEIOLATCH%'</span><span> </span><span class="op">and</span><span> waiting_tasks_count > 0 </span></span></li><li><span><span class="keyword">order</span><span> </span><span class="keyword">by</span><span> wait_type </span></span></li></ol> |
如果 waiting_task_counts 和 wait_time_ms 与正常情况相比有显著变化,则可以确定存在 I/O 问题。获取 SQL Server 平稳运行时性能计数器和主要 DMV 查询输出的基线非常重要。
这些 wait_types 可以指示您的 I/O 子系统是否遇到瓶颈。
使用以下 DMV 查询来查找当前挂起的 I/O 请求。请定期执行此查询以检查 I/O 子系统的运行状况,并隔离 I/O 瓶颈中涉及的物理磁盘。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> </span></span></li><li><span> database_id, </span></li><li class="alt"><span> file_id, </span></li><li><span> io_stall, </span></li><li class="alt"><span> io_pending_ms_ticks, </span></li><li><span> scheduler_address </span></li><li class="alt"><span><span class="keyword">from</span><span> sys.dm_io_virtual_file_stats(</span><span class="op">NULL</span><span>, </span><span class="op">NULL</span><span>)t1, </span></span></li><li><span> sys.dm_io_pending_io_requests <span class="keyword">as</span><span> t2 </span></span></li><li class="alt"><span><span class="keyword">where</span><span> t1.file_handle = t2.io_handle </span></span></li></ol> |
在正常情况下,该查询通常不返回任何内容。如果此查询返回一些行,则需要进一步调查。
您还可以执行下面的 DMV 查询以查找 I/O 相关查询。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> </span><span class="keyword">top</span><span> 5 (total_logical_reads/execution_count) </span><span class="keyword">as</span><span> avg_logical_reads, </span></span></li><li><span> (total_logical_writes/execution_count) <span class="keyword">as</span><span> avg_logical_writes, </span></span></li><li class="alt"><span> (total_physical_reads/execution_count) <span class="keyword">as</span><span> avg_physical_reads, </span></span></li><li><span> Execution_count, statement_start_offset, p.query_plan, q.text </span></li><li class="alt"><span><span class="keyword">from</span><span> sys.dm_exec_query_stats </span></span></li><li><span> <span class="op">cross</span><span> apply sys.dm_exec_query_plan(plan_handle) p </span></span></li><li class="alt"><span> <span class="op">cross</span><span> apply sys.dm_exec_sql_text(plan_handle) </span><span class="keyword">as</span><span> q </span></span></li><li><span><span class="keyword">order</span><span> </span><span class="keyword">by</span><span> (total_logical_reads + total_logical_writes)/execution_count </span><span class="keyword">Desc</span><span> </span></span></li></ol> |
下面的 DMV 查询可用于查找哪些批处理/请求生成的 I/O 最多。如下所示的 DMV 查询可用于查找可生成最多 I/O 的前五个请求。调整这些查询将提高系统性能。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> </span><span class="keyword">top</span><span> 5 </span></span></li><li><span> (total_logical_reads/execution_count) <span class="keyword">as</span><span> avg_logical_reads, </span></span></li><li class="alt"><span> (total_logical_writes/execution_count) <span class="keyword">as</span><span> avg_logical_writes, </span></span></li><li><span> (total_physical_reads/execution_count) <span class="keyword">as</span><span> avg_phys_reads, </span></span></li><li class="alt"><span> Execution_count, </span></li><li><span> statement_start_offset <span class="keyword">as</span><span> stmt_start_offset, </span></span></li><li class="alt"><span> sql_handle, </span></li><li><span> plan_handle </span></li><li class="alt"><span><span class="keyword">from</span><span> sys.dm_exec_query_stats </span></span></li><li><span><span class="keyword">order</span><span> </span><span class="keyword">by</span><span> (total_logical_reads + total_logical_writes) </span><span class="keyword">Desc</span><span> </span></span></li></ol> |
运行下面的查询可确定阻塞的会话。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> blocking_session_id, wait_duration_ms, session_id </span><span class="keyword">from</span><span> </span></span></li><li><span>sys.dm_os_waiting_tasks </span></li><li class="alt"><span><span class="keyword">where</span><span> blocking_session_id </span><span class="keyword">is</span><span> </span><span class="op">not</span><span> </span><span class="op">null</span><span> </span></span></li></ol> |
使用此调用可找出 blocking_session_id 所返回的 SQL。例如,如果 blocking_session_id 是 87,则运行此查询可获得相应的 SQL。
1 |
<ol class="dp-sql"><li class="alt"><span><span>dbcc INPUTBUFFER(87) </span></span></li></ol> |
下面的查询显示 SQL 等待分析和前 10 个等待的资源。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">select</span><span> </span><span class="keyword">top</span><span> 10 * </span></span></li><li><span><span class="keyword">from</span><span> sys.dm_os_wait_stats </span></span></li><li class="alt"><span><span class="comment">--where wait_type not in ('CLR_SEMAPHORE','LAZYWRITER_SLEEP','RESOURCE_QUEUE','SLEEP_TASK','SLEEP_SYSTEMTASK','WAITFOR')</span><span> </span></span></li><li><span><span class="keyword">order</span><span> </span><span class="keyword">by</span><span> wait_time_ms </span><span class="keyword">desc</span><span> </span></span></li></ol> |
若要找出哪个 spid 正在阻塞另一个 spid,可在数据库中创建以下存储过程,然后执行该存储过程。此存储过程会报告此阻塞情况。键入 sp_who 可找出 @spid;@spid 是可选参数。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">create</span><span> proc dbo.sp_block (@spid </span><span class="keyword">bigint</span><span>=</span><span class="op">NULL</span><span>) </span></span></li><li><span><span class="keyword">as</span><span> </span></span></li><li class="alt"><span><span class="keyword">select</span><span> </span></span></li><li><span> t1.resource_type, </span></li><li class="alt"><span> <span class="string">'database'</span><span>=db_name(resource_database_id), </span></span></li><li><span> <span class="string">'blk object'</span><span> = t1.resource_associated_entity_id, </span></span></li><li class="alt"><span> t1.request_mode, </span></li><li><span> t1.request_session_id, </span></li><li class="alt"><span> t2.blocking_session_id </span></li><li><span><span class="keyword">from</span><span> </span></span></li><li class="alt"><span> sys.dm_tran_locks <span class="keyword">as</span><span> t1, </span></span></li><li><span> sys.dm_os_waiting_tasks <span class="keyword">as</span><span> t2 </span></span></li><li class="alt"><span><span class="keyword">where</span><span> </span></span></li><li><span> t1.lock_owner_address = t2.resource_address <span class="op">and</span><span> </span></span></li><li class="alt"><span> t1.request_session_id = <span class="func">isnull</span><span>(@spid,t1.request_session_id) </span></span></li></ol> |
以下是使用此存储过程的示例。
1 |
<ol class="dp-sql"><li class="alt"><span><span class="keyword">exec</span><span> sp_block </span></span></li><li><span><span class="keyword">exec</span><span> sp_block @spid = 7 </span></span></li></ol> |
原文链接:http://www.cnblogs.com/jiguixin/archive/2011/01/05/1926235.html