【问题标题】:Capturing Top 100 Costly queries in SQL Server (<2014)捕获 SQL Server 中成本最高的 100 个查询 (<2014)
【发布时间】:2016-10-12 19:42:32
【问题描述】:

我正在尝试每天捕获成本高昂的查询并将其保存到表中以供进一步分析。我正在使用每天晚上运行的日常工作来执行此操作。

使用以下代码捕获代价高昂的查询:

CREATE TABLE [dbo].[CostlyQueries](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [QueryText] [nvarchar](max) NULL,
    [execution_count] [bigint] NOT NULL,
    [total_logical_reads] [bigint] NOT NULL,
    [last_logical_reads] [bigint] NOT NULL,
    [total_logical_writes] [bigint] NOT NULL,
    [last_logical_writes] [bigint] NOT NULL,
    [total_worker_time] [bigint] NOT NULL,
    [last_worker_time] [bigint] NOT NULL,
    [total_elapsed_time_in_S] [bigint] NULL,
    [last_elapsed_time_in_S] [bigint] NULL,
    [last_execution_time] [datetime] NULL,
    [query_plan] [xml] NULL,
    [DateAdded] [datetime] NULL DEFAULT (getdate())
)


INSERT INTO CostlyQueries (QueryText, execution_count, total_logical_reads, last_logical_reads, total_logical_writes, [last_logical_writes], total_worker_time, last_worker_time
    , total_elapsed_time_in_S, last_elapsed_time_in_S, last_execution_time, query_plan )
SELECT TOP 100 SUBSTRING(qt.TEXT, (qs.statement_start_offset/2)+1,
    ((CASE qs.statement_end_offset
    WHEN -1 THEN DATALENGTH(qt.TEXT)
    ELSE qs.statement_end_offset
    END - qs.statement_start_offset)/2)+1) AS QueryText,
    qs.execution_count,
    qs.total_logical_reads, qs.last_logical_reads,
    qs.total_logical_writes, qs.last_logical_writes,
    qs.total_worker_time,
    qs.last_worker_time,
    qs.total_elapsed_time/1000000 total_elapsed_time_in_S,
    qs.last_elapsed_time/1000000 last_elapsed_time_in_S,
    qs.last_execution_time,
    qp.query_plan
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY last_elapsed_time_in_S desc,
qs.total_worker_time DESC -- CPU time

这里有两个问题:

  1. 这些 DMV(系统数据)何时刷新?在我读到的某个地方,它将在 sql 服务的回收过程中被刷新。谁有这方面的详细信息?

  2. 我编写的用于捕获代价高昂的查询的查询使用 sys.dm_exec_query_stats,由于某种原因,它没有在周末捕获长时间运行的查询。任何人都可以帮助更正/获取更多详细信息,以便我们可以捕获更多指标吗?

按照 Aaron Bertrand 在下面的 cmets 中的建议添加了正确的查询:- 将交叉应用更改为外部应用 -

SELECT TOP 100 SUBSTRING(qt.TEXT, (qs.statement_start_offset/2)+1,
    ((CASE qs.statement_end_offset
    WHEN -1 THEN DATALENGTH(qt.TEXT)
    ELSE qs.statement_end_offset
    END - qs.statement_start_offset)/2)+1) AS QueryText,
    qs.execution_count,
    qs.total_logical_reads, qs.last_logical_reads,
    qs.total_logical_writes, qs.last_logical_writes,
    qs.total_worker_time,
    qs.last_worker_time,
    qs.total_elapsed_time/1000000 total_elapsed_time_in_S,
    qs.last_elapsed_time/1000000 last_elapsed_time_in_S,
    qs.last_execution_time,
    qp.query_plan
FROM sys.dm_exec_query_stats qs
OUTER APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
OUTER APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY last_elapsed_time_in_S desc,
qs.total_worker_time DESC -- CPU time

【问题讨论】:

    标签: sql-server sql-server-2008 tsql sql-server-2012


    【解决方案1】:

    只要计划在缓存中,数据就会保留在 DMV 中。由于多种不同的原因(内存压力、重新编译等),计划可能会从缓存中删除。此外,更改设置或重新启动服务器等各种事情当然会刷新所有内容。

    如果你想让它有点可靠,你必须经常运行它,以免丢失任何重要的东西。

    【讨论】:

    • 您还可以将 CROSS APPLY 更改为 OUTER APPLY,这样即使在缓存中没有找到计划,您仍然可以获得有关长时间运行的查询的信息。
    • 这是否意味着 QueryText 和 QueryPlan 可能会在查询统计信息之前刷新?
    • @Kannan 当然,查询计划可能由于各种原因从计划缓存中被逐出,并且在某些情况下,查询一开始就无法在缓存中注册计划。
    【解决方案2】:

    进行自己的分析并没有错,因为它始终 100% 适合您的需求,但是,我建议您也查看 SQL Server 数据收集器和Data Collection Sets

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 2017-08-06
      相关资源
      最近更新 更多