1

我一直在学习有关 sql server 中动态管理视图的更多信息,因为我们在工作中遇到了一些性能问题。也许这是看待事物的错误方式,但可用的工具似乎......它们似乎不像我想要的那样灵活。

我希望能够找出以下我有示例的内容。

哪些查询的运行速度比正常情况慢 20% 以上?以下 ...

--displays regarding about procedures that are currently taking longer to execute by more than 20% over the average. 
;
with data as (
select  s.plan_handle
        , db.name
        , ObjectName = OBJECT_NAME(t.objectid, t.dbid )
        , PlanCompileDate = s.creation_time
        , PlanExecutionCount = execution_count

        , AvgElapsedSeconds = ( total_elapsed_time/ CAST( 1000000 as float(15) ) ) / CAST( s.execution_count as float(15) )
        , LastElapsedSeconds = last_elapsed_time / CAST( 1000000 as float(38) )
        , LeastElapsedSeconds = min_elapsed_time / CAST( 1000000 as float(15) )
        , MostElapsedSeconds = max_elapsed_time / CAST( 1000000 as float(15) )
        , LastExecPercentageDevTime = (( ( s.total_elapsed_time /  cast(s.execution_count as float(15) ) ) - s.last_elapsed_time ) / ( case s.last_elapsed_time when 0 then -1.00 else ( s.total_elapsed_time /  cast( s.execution_count as float(15) ) ) end ) )  * -100
                                                    -- 0.00532225 
        , AvgRowsReturned = total_rows / CAST( s.execution_count as float )
        , LastRowsReturned = last_rows
        , LeastRowsReturned = min_rows
        , MostRowsReturned = max_rows
        , LastExecPercentageDevRows =  (( ( s.total_rows /  cast(s.execution_count as float ) ) - s.last_rows) / ( case s.last_rows when 0 then -1.00 else ( s.total_rows /  cast( s.execution_count as float ) ) end ) )  * -100 

        , AvgCPUTime = s.total_worker_time / CAST( s.execution_count as float )
        , LastCPUTime = s.last_worker_time
        , LeastCPUTime = min_worker_time
        , MostCPUTime = max_worker_time
        , LastExecPercentageDevCPUTime =  (( ( s.total_worker_time /  cast(s.execution_count as float ) ) - s.last_worker_time ) / ( case s.last_worker_time when 0 then -1.00 else ( s.total_worker_time /  cast( s.execution_count as float ) ) end ) )  * -100 

        , AvgPhysicalReads = s.total_physical_reads / CAST( s.execution_count as float )
        , LastPhysicalReads = s.last_physical_reads
        , LeastPhysicalReads = s.min_physical_reads
        , MostPhysicalReads = s.max_physical_reads
        , LastExecPercentageDevPhysicalReads = (( ( s.total_physical_reads /  cast(s.execution_count as float ) ) - s.last_physical_reads ) / ( case s.last_physical_reads when 0 then -1.00 else ( s.total_physical_reads /  cast( s.execution_count as float ) ) end ) )  * -100 

        , AvgLogicalReads = s.total_logical_reads / CAST( s.execution_count as float )
        , LastLogicalReads = s.last_logical_reads
        , LeastLogicalReads = s.min_logical_reads
        , MostLogicalReads = s.max_logical_reads
        , LastExecPercentageDevLogicalReads = (( ( s.total_logical_reads /  cast(s.execution_count as float ) ) - s.last_logical_reads ) / ( case s.last_logical_reads when 0 then -1.00 else ( s.total_logical_reads /  cast( s.execution_count as float ) ) end ) )  * -100 

        , AvgLogicalWrites = s.total_logical_Writes / CAST( s.execution_count as float )
        , LastLogicalWrites = s.last_logical_Writes
        , LeastLogicalWrites = s.min_logical_Writes
        , MostLogicalWrites = s.max_logical_Writes
        , LastExecPercentageDevLogicalWrites = (( ( s.total_logical_writes /  cast(s.execution_count as float ) ) - s.last_logical_writes ) / ( case s.last_logical_writes when 0 then -1.00 else ( s.total_logical_writes /  cast( s.execution_count as float ) ) end ) )  * -100 

        , t.text
        , t.number
        , t.objectid
        , s.query_hash
        --, s.* 
FROM sys.dm_exec_query_stats AS s 
     CROSS APPLY sys.dm_exec_sql_text(s.sql_handle) AS t 
     LEFT JOIN sys.databases AS DB 
        ON t.dbid = DB.database_id
)
select  *
from    data 
where   LastExecPercentageDevTime > 20 and -- changed by at least 20%
        PlanExecutionCount > 10 and -- executed more than 10 times 
        LastElapsedSeconds != 0 -- we don't care about queries that executed quickly
order by LastExecPercentageDevTime desc

当有阻塞时,我希望能够确定正在执行阻塞的查询,也许它的依赖对象是什么。

我相信以下内容可以找到执行阻塞的查询

-- What queries are the source of all the blocking.
with blockingSessions as(
    select session_id,blocking_session_id
    from sys.dm_exec_requests
    where blocking_session_id > 0
), causal as(
    select  blocking_session_id
    from    blockingSessions
    where   blocking_session_id not in(select session_id from blockingSessions)
)--select * from causal 
select   t.text
        ,SPID               = con.most_recent_session_id
        ,STATUS             = s.STATUS
        ,[Login]            = s.login_name
        ,Host               = s.host_name
        --,BlkBy              = r.blocking_session_id
        ,DBName             = d.name
        ,CommandType        = r.command
        ,SQLStatement       = t.text
        ,ObjectName         = OBJECT_NAME(t.objectid)
        ,ElapsedMS          = r.total_elapsed_time
        ,CPUTime            = r.cpu_time
        ,IOReads            = r.logical_reads + r.reads
        ,IOWrites           = r.writes
        ,LastWaitType       = r.last_wait_type
        ,StartTime          = r.start_time
        ,Protocol           = con.net_transport
        ,ConnectionWrites   = con.num_writes
        ,ConnectionReads    = con.num_reads
        ,ClientAddress      = con.client_net_address
        ,Authentication     = con.auth_scheme 
        --,t.*
from    causal c
        join sys.dm_exec_connections con
            on c.blocking_session_id = con.session_id
        join sys.dm_exec_sessions s
            on con.most_recent_session_id = s.session_id
        left join sys.dm_exec_requests r
            on s.session_id = r.session_id
        outer APPLY sys.dm_exec_sql_text(con.most_recent_sql_handle) AS t
        left join sys.databases d   
            on t.dbid = d.database_id

但我一直无法弄清楚如何实现以下...

今天特定查询运行了多少次(不是自上次计划编译时间以来)?今天一个特定的存储过程今天运行了多少次?使用某些参数调用了多少次?

也许还有其他一些你们可以想到的有用的,也许你们可以为我上面给出的提供一些建议。我无法弄清楚的另一件事是动态管理视图中的连接、请求和会话之间的关系到底是什么?

编辑

我想我是专门尝试在特定时间段内使用视图,例如在 x 时间和 y 时间之间发生的情况。但它们似乎不是为此而设计的。这个对吗?是否有另一种方法可以从 sql server 按时间段获取类似信息?

4

1 回答 1

2

如果您正在考虑使用 DMV 来了解有关 SQL Server 数据库/服务器的更多信息,请前往Glenn Berry 的 SQL Server 诊断信息查询

以下是他的 SQL Server 2008 R2 中的一些查询:按执行次数排列的热门查询:

    SELECT TOP (250) qs.execution_count, qs.total_rows, qs.last_rows, qs.min_rows, qs.max_rows, qs.last_elapsed_time, qs.min_elapsed_time, qs.max_elapsed_time,
total_worker_time, total_logical_reads, 
SUBSTRING(qt.TEXT,qs.statement_start_offset/2 +1,
(CASE WHEN qs.statement_end_offset = -1
            THEN LEN(CONVERT(NVARCHAR(MAX), qt.TEXT)) * 2
      ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) AS query_text 
FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK)
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
ORDER BY qs.execution_count DESC OPTION (RECOMPILE);

按执行次数排名最高的 SP:

SELECT TOP(250) p.name AS [SP Name], qs.execution_count,
ISNULL(qs.execution_count/DATEDIFF(Second, qs.cached_time, GETDATE()), 0) AS [Calls/Second],
qs.total_worker_time/qs.execution_count AS [AvgWorkerTime], qs.total_worker_time AS [TotalWorkerTime],  
qs.total_elapsed_time, qs.total_elapsed_time/qs.execution_count AS [avg_elapsed_time],
qs.cached_time
FROM sys.procedures AS p WITH (NOLOCK)
INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (NOLOCK)
ON p.[object_id] = qs.[object_id]
WHERE qs.database_id = DB_ID()
ORDER BY qs.execution_count DESC OPTION (RECOMPILE);

您可以轻松地修改这些以获取执行查询/SP 的次数。

于 2013-04-12T02:05:16.557 回答