SQL编译对SQL Server的性能有多严重的影响?


20

我正在分析一个SQL Server 2005实例,通过PerfMon的SQLServer:SQL Statistics - SQL Compilations/sec指标,我发现平均值约为170左右。

我剔除了SQL事件探查器,并寻找SP:Compile或SQL:Compile事件。显然它们不存在。我没有找到Stored Procedure/SP:RecompileTSQL/SQL:StmtRecompile事件。我在探查器中看到的数据量表明这些是看错的事件,尽管我不确定。

所以我的问题。任何一个答案都是不错的。

  1. 如何查看SQL Server中正在编译的内容?
  2. 我选择了错误的指标来查看吗?在Perfmon还是SQL Profiler中?
  3. 关于Stored Procedure/SP:RecompileTSQL/SQL:StmtRecompileSQL事件探查器中的事件...它们不包括“持续时间”度量标准。如果无法提供查看事件对系统的影响的方法,那么如何评估这些事件对系统的影响。

Answers:


33

SQL编译/秒是一个很好的指标,但仅当与Batch Requests / sec结合使用时。就其本身而言,每秒编译量并不能真正告诉您太多信息。

您将看到170。如果每秒的批处理请求数仅为200(效果有点夸张),则是,您需要深入分析原因(很可能是临时查询和一次性计划的过度使用)。但是,如果您的批处理每秒请求量约为5000,那么每秒170次编译就完全不错。一般的经验法则是,“ 编译/秒”应为“总批处理请求/秒”的 10%或以下。

如果您真的想深入了解正在缓存的内容,请运行以下使用适当DMV的查询:

select
    db_name(st.dbid) as database_name,
    cp.bucketid,
    cp.usecounts,
    cp.size_in_bytes,
    cp.objtype,
    st.text
from sys.dm_exec_cached_plans cp
cross apply sys.dm_exec_sql_text(cp.plan_handle) st

要获得所有一次性使用计划(计数):

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
)
select count(*)
from PlanCacheCte
where usecounts = 1

要获得您与所有缓存计划相比有多少个一次性计数计划的比率:

declare @single_use_counts int, @multi_use_counts int

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
    where cp.cacheobjtype = 'Compiled Plan'
)
select @single_use_counts = count(*)
from PlanCacheCte
where usecounts = 1

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
    where cp.cacheobjtype = 'Compiled Plan'
)
select @multi_use_counts = count(*)
from PlanCacheCte
where usecounts > 1

select
    @single_use_counts as single_use_counts,
    @multi_use_counts as multi_use_counts,
    @single_use_counts * 1.0 / (@single_use_counts + @multi_use_counts) * 100
        as percent_single_use_counts

至于通过SQL Server跟踪捕获的持续时间,它不适用于重新编译事件。查看计划编制所导致的持续时间或痛苦并不那么重要,因为对于个案情况您无能为力。解决方案是尝试通过计划重用(参数化查询,存储过程等)来限制编译和重新编译。


9

使用PerfMon(或其他第三方解决方案)应记录三个相关的计数器。关键是要以某种方式记录这些统计数据。

  • SQL统计信息\批量请求/秒
  • SQL统计信息\ SQL编译/秒
  • SQL Statistics \ SQL重新编译/秒

正如Thomas Stringer所提到的,请密切注意编译/批处理请求的比率。显然,越低越好,但是只有什么是“好”的准则,只有您才能决定什么是可以接受的。通过减少编译次数可以看到的绝对性能提高取决于许多因素。

我还想看看重新编译/编译比率,以了解查询计划重用的数量。同样,越低越好。但是,在这种情况下,您确实希望随着统计信息的变化而在系统中进行重新编译(如果DB是只读的,并且您具有重新编译的功能,则可能是错误的)。与我之前说的一样,只有什么是“好”的准则。

您真正想要做的是随着时间的推移使这些数字趋于趋势,因此,如果您看到两个比率中的任何一个都急剧增加,则表明部署了某些未正确使用查询计划的对象(理想情况下,这会在测试期间被捕获)-使用Shark的分析查询以找出罪魁祸首。此外,这是查找经常重新编译的查询的一种:

SELECT TOP 50
    qs.plan_generation_num,
    qs.execution_count,
    qs.statement_start_offset,
    qs.statement_end_offset,
    st.text
    FROM sys.dm_exec_query_stats qs
    CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
    WHERE qs.plan_generation_num > 1
    ORDER BY qs.plan_generation_num DESC

如果您还记录CPU使用情况的统计信息,则可以将所有统计信息关联在一起,以找出造成的损失以及您的修复有多少帮助。在实践中,我发现即使是核心存储上的单个错误查询计划策略也可以使服务器瘫痪。显然是YMMV。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.