SQLServer数据库优化与管理——硬件资源篇

要对当前已经在使用的SQLSERVER系统的硬件资源进行检查。下面的脚本可以运行在当前系统方便找出硬件的信息,用户可以根据具体的硬件信息对数据库进行调优处理。

查看数据库中的 IO情况

-- 当前数据库文件的I/O 统计信息
SELECT  DB_NAME(DB_ID()) AS [Database Name] ,
        [file_id] ,
        num_of_reads ,
        num_of_writes ,
        num_of_bytes_read ,
        num_of_bytes_written ,
        CAST(100. * num_of_reads / ( num_of_reads + num_of_writes ) AS DECIMAL(10,
                                                              1)) AS [# Reads Pct] ,
        CAST(100. * num_of_writes / ( num_of_reads + num_of_writes ) AS DECIMAL(10,
                                                              1)) AS [# Write Pct] ,
        CAST(100. * num_of_bytes_read / ( num_of_bytes_read
                                          + num_of_bytes_written ) AS DECIMAL(10,
                                                              1)) AS [Read Bytes Pct] ,
        CAST(100. * num_of_bytes_written / ( num_of_bytes_read
                                             + num_of_bytes_written ) AS DECIMAL(10,
                                                              1)) AS [Written Bytes Pct]
FROM    sys.dm_io_virtual_file_stats(DB_ID(), NULL);

除了这个脚本,还有其他3个脚本可用于检查当前系统的读写情况,如代码清单。
–计划缓存中存储过程的逻辑写排名 (SQL 2008 and 2008 R2 适用) ,主要是写操作的压力

--计划缓存中存储过程的逻辑写排名 (SQL 2008 and 2008 R2 适用) ,主要是写操作的压力
SELECT  p.name AS [SP Name] ,
        qs.total_logical_writes AS [TotalLogicalWrites] ,
        qs.total_logical_reads AS [TotalLogicalReads] ,
        qs.execution_count ,
        qs.cached_time
FROM    sys.procedures AS p
        INNER JOIN sys.dm_exec_procedure_stats AS qs ON p.[object_id] = qs.[object_id]
WHERE   qs.database_id = DB_ID()
        AND qs.total_logical_writes > 0
ORDER BY qs.total_logical_writes DESC;

计划缓存中存储过程的物理读排名 (SQL 2008 and 2008 R2 适用) ,主要是读操作的压力

--计划缓存中存储过程的物理读排名 (SQL 2008 and 2008 R2 适用) ,主要是读操作的压力
SELECT  p.name AS [SP Name] ,
        qs.total_physical_reads AS [TotalPhysicalReads] ,
        qs.total_logical_reads AS [TotalLogicalReads] ,
        qs.total_physical_reads / qs.execution_count AS [AvgPhysicalReads] ,
        qs.execution_count ,
        qs.cached_time
FROM    sys.procedures AS p
        INNER JOIN sys.dm_exec_procedure_stats AS qs ON p.[object_id] = qs.[object_id]
WHERE   qs.database_id = DB_ID()
        AND qs.total_physical_reads > 0
ORDER BY qs.total_physical_reads DESC ,
        qs.total_logical_reads DESC;

计划缓存中存储过程的逻辑写排名

SELECT  p.name AS [SP Name] ,
        qs.total_logical_reads AS [TotalLogicalReads] ,
        qs.total_logical_writes AS [TotalLogicalWrites] ,
        qs.execution_count ,
        qs.cached_time
FROM    sys.procedures AS p
        INNER JOIN sys.dm_exec_procedure_stats AS qs ON p.[object_id] = qs.[object_id]
WHERE   qs.database_id = DB_ID()
        AND qs.total_logical_reads > 0
ORDER BY qs.total_logical_reads DESC;

研究CPU相关的等待信息

当一个请求由于某些原因产生等待时,SQL Server会把相关信息存放在sys.dm_os.
wait_stats这个DMV中。很多第三方工具都是通过分析这个DMV中的信息进行问题侦测
的,下面来看个例子。
比如可以用下面语句检查等待类型中等待时间最长的10个类型。

SELECT TOP ( 10 )
        wait_type ,
        waiting_tasks_count ,
        ( wait_time_ms - signal_wait_time_ms ) AS resource_wait_time ,
        max_wait_time_ms ,
        CASE waiting_tasks_count
          WHEN 0 THEN 0
          ELSE wait_time_ms / waiting_tasks_count
        END AS avg_wait_time
FROM    sys.dm_os_wait_stats
WHERE   wait_type NOT LIKE '%SLEEP%'   -- 去除不相关的等待类型
        AND wait_type NOT LIKE 'XE%'
        AND wait_type NOT IN -- 去除系统类型   
( 'KSOURCE_WAKEUP', 'BROKER_TASK_STOP', 'FT_IFTS_SCHEDULER_IDLE_WAIT',
  'SQLTRACE_BUFFER_FLUSH', 'CLR_AUTO_EVENT', 'BROKER_EVENTHANDLER',
  'BAD_PAGE_PROCESS', 'BROKER_TRANSMITTER', 'CHECKPOINT_QUEUE',
  'DBMIRROR_EVENTS_QUEUE', 'SQLTRACE_BUFFER_FLUSH', 'CLR_MANUAL_EVENT',
  'ONDEMAND_TASK_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'LOGMGR_QUEUE',
  'BROKER_RECEIVE_WAITFOR', 'PREEMPTIVE_OS_GETPROCADDRESS',
  'PREEMPTIVE_OS_AUTHENTICATIONOPS', 'BROKER_TO_FLUSH' )
ORDER BY wait_time_ms DESC 

查找 CPU 消耗高的查询

下面的语句用于查找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

非必要的并行查询

并行操作会把一个查询分开到多个线程中执行,然后再合并到一起返回结果。当-个
查询的开销超过cost threshold for parallelism这个阈值时(默认为5秒),就会检查是否有可
用的CPU用于支持并行操作,其中,并行度取决于max degree of parallelism的值。但是
对于OLTP 系统,并行操作往往是非必需的,过多的并行执行会加重CPU的负担。可以用
下面语句来检查是否存在并行操作的执行计划。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;  
 
WITH XMLNAMESPACES 
   (DEFAULT 'http://schemas.microsoft.com/SQL Server/2004/07/showplan')   
SELECT query_plan AS CompleteQueryPlan , 
        n.value('(@StatementText)[1]', 'VARCHAR(4000)') AS StatementText , 
        n.value('(@StatementOptmLevel)[1]', 'VARCHAR(25)') 
                  AS StatementOptimizationLevel , 
        n.value('(@StatementSubTreeCost)[1]', 'VARCHAR(128)') 
                  AS StatementSubTreeCost , 
        n.query('.') AS ParallelSubTreeXML , 
        ecp.usecounts , 
        ecp.size_in_bytes 
FROM    sys.dm_exec_cached_plans AS ecp 
        CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS eqp CROSS APPLY query_plan.nodes 
               ('/ShowPlanXML/BatchSequence/Batch/Statements/StmtSimple') 
        AS qn ( n ) 
WHERE   n.query('.').exist('//RelOp[@PhysicalOp="Parallelism"]') = 1

你可能感兴趣的:(sql,server,数据库,数据库调优,数据库,运维)