如何确定存储过程是否每次都重新编译?

时间:2008-11-26 01:41:20

标签: sql sql-server tsql

我有一个SQL Server存储过程,其中包含以下T-SQL代码:

insert into #results ([ID], [Action], [Success], [StartTime], [EndTime], [Process])
select
    'ID' = aa.[ActionID],
    'Action' = cast(aa.[Action] as int),
    'Success' = aa.[Success],
    'StartTime' = aa.[StartTime],
    'EndTime' = aa.[EndTime],
    'Process' = cast(aa.[Process] as int)
from
    [ApplicationActions] aa with(nolock)
where
    0 = case
            when (@loggingLevel = 0) then 0
            when (@loggingLevel = 1 and aa.[LoggingLevel] = 1) then 0
        end
    and
    1 = case
            when (@applicationID is null) then 1
            when (@applicationID is not null and aa.[ApplicationID] = @applicationID) then 1
        end
    and
    2 = case
            when (@startDate is null) then 2
            when (@startDate is not null and aa.[StartTime] >= @startDate) then 2
        end
    and
    3 = case
            when (@endDate is null) then 3
            when (@endDate is not null and aa.[StartTime] <= @endDate) then 3
        end
    and
    4 = case
            when (@success is null) then 4
            when (@success is not null and aa.[Success] = @success) then 4
        end
    and
    5 = case
            when (@process is null) then 5
            when (@process is not null and aa.[Process] = @process) then 5
        end

这是困扰我的“动态”WHERE子句。用户不必将每个参数传递给此存储过程。只是他们有兴趣用作输出过滤器的那些。

如何使用SQL Server Studio或Profiler测试此存储过程是否每次都重新编译?

3 个答案:

答案 0 :(得分:1)

只是随便,您可以简化这些:

    2 = case
                    when (@startDate is null) then 2
                    when (@startDate is not null and aa.[StartTime] >= @startDate) then 2
            end

到此:

    (@startDate is null OR aa.[StartTime] >= @startDate)

就重新编译而言 - 它是否声明为WITH RECOMPILE

答案 1 :(得分:1)

以下文章介绍了如何确定存储过程是否正在重新编译: http://it.toolbox.com/blogs/programming-life/sql-performance-abnormal-stored-procedure-recompiles-8105

以下是相应部分的引用:

  

启动SQL事件探查器并启动新的   跟踪,连接到我们的服务器并给予   一个合适的跟踪名称,选择   事件选项卡并删除已经   “选定活动”上的现有活动   类“列表框。现在选择   “存储过程”节点中的   “可用的事件类”并添加   SPComplete,SPRecompile,SPStarting,   SP:StmtStarting和SP:StmtCompleted。   现在选择“数据列”选项卡和   选择恰到好处的数量   您需要的事件和数据列。   添加过滤器以减少数量   你收集的事件。

我会按存储过程的名称进行过滤。

答案 2 :(得分:1)

您插入示例中的临时表,导致每次都重新编译SP,因为它无法预编译。

这是使用临时表和表变量之间的差异之一 - 可以找到关于差异的好文章here

相关提取物......

  

第二个主要区别是   任何带临时表的过程   不能预先编译,而一个   执行计划的程序   表变量可以是静态的   事先编译。预编译a   脚本给它带来了一个主要优势   执行速度。这个优势可以   对于漫长的程序来说是戏剧性的   重新编译可能过于昂贵。