2016-06-17 108 views
1

将此作为一个更广泛的问题发布,但请让我知道实际查询是否有助于解决此问题。选项(重新编译)加快查询执行速度

我们有一个查询需要约30秒的时间来执行,由于执行计划的判断有多种原因。查询由实体框架生成,当然有一些低效率,所以这不是重点。

当我们DBCC FREEPROCCACHE并提交查询时,原来〜30秒的运行时间。当使用OPTION(RECOMPILE)暗示查询时,它是即时的(并且计划更加合理)。

如果查询在第一个场景中第一次遇到服务器,为什么结果会不一致,因此应该第一次编译计划?

旁注: - 4136等

  • 跟踪标志在去之前

    更新 - 增加计划:

  • +1

    这是一个参数嗅探问题的脚印之一。 – RBarryYoung

    +0

    可能受益于[参数嵌入优化](http://sqlperformance.com/2013/08/t-sql-queries/parameter-sniffing-embedding-and-the-recompile-options)没有查询和计划谁知道? –

    +0

    如果您将“好”计划与重新编译和“坏”计划进行比较,您应该弄清楚有什么不同。用于编译它的参数位于最左边的节点中。 –

    回答

    0

    这看起来并不像参数嗅探。

    的CompiledValue和RunTimeValue是所有参数不变,即使在bad.sqlplan

    <ParameterList> 
        <ColumnReference Column="@p__linq__16" ParameterCompiledValue="(8)" ParameterRuntimeValue="(8)" /> 
        <ColumnReference Column="@p__linq__15" ParameterCompiledValue="N'ABCD4'" ParameterRuntimeValue="N'ABCD4'" /> 
        <ColumnReference Column="@p__linq__14" ParameterCompiledValue="(10776)" ParameterRuntimeValue="(10776)" /> 
        <ColumnReference Column="@p__linq__13" ParameterCompiledValue="(8)" ParameterRuntimeValue="(8)" /> 
        <ColumnReference Column="@p__linq__12" ParameterCompiledValue="(0)" ParameterRuntimeValue="(0)" /> 
        <ColumnReference Column="@p__linq__11" ParameterCompiledValue="N'ABCD4'" ParameterRuntimeValue="N'ABCD4'" /> 
        <ColumnReference Column="@p__linq__10" ParameterCompiledValue="N'ABCD4'" ParameterRuntimeValue="N'ABCD4'" /> 
        <ColumnReference Column="@p__linq__9" ParameterCompiledValue="NULL" ParameterRuntimeValue="NULL" /> 
        <ColumnReference Column="@p__linq__8" ParameterCompiledValue="NULL" ParameterRuntimeValue="NULL" /> 
        <ColumnReference Column="@p__linq__7" ParameterCompiledValue="NULL" ParameterRuntimeValue="NULL" /> 
        <ColumnReference Column="@p__linq__6" ParameterCompiledValue="N'ABCD4'" ParameterRuntimeValue="N'ABCD4'" /> 
        <ColumnReference Column="@p__linq__5" ParameterCompiledValue="(8)" ParameterRuntimeValue="(8)" /> 
        <ColumnReference Column="@p__linq__4" ParameterCompiledValue="(513)" ParameterRuntimeValue="(513)" /> 
        <ColumnReference Column="@p__linq__3" ParameterCompiledValue="(8)" ParameterRuntimeValue="(8)" /> 
        <ColumnReference Column="@p__linq__2" ParameterCompiledValue="(513)" ParameterRuntimeValue="(513)" /> 
        <ColumnReference Column="@p__linq__1" ParameterCompiledValue="(8)" ParameterRuntimeValue="(8)" /> 
        <ColumnReference Column="@p__linq__0" ParameterCompiledValue="(513)" ParameterRuntimeValue="(513)" /> 
    </ParameterList> 
    

    相反,它看起来好像你是从The Parameter Embedding Optimization受益。

    查询文本在计划中被截断,但我可以看到您正在比较参数与文字的位置。也许这是一个catch all query

    enter image description here

    当您使用OPTION (RECOMPILE)计划编制具有用于传递的参数值工作。 SQL Server可以查看传递参数的值,并用TRUEFALSE有效替换突出显示的表达式。

    这可能允许它简化计划的整个分支,如果它们与传递的参数值无关。

    这方面的一个简单的例子是

    EXEC sys.sp_executesql 
        N'SELECT * FROM master..spt_values WHERE @Param <> 0 OPTION (RECOMPILE)', 
        N'@Param INT', 
        @Param = 0; 
    

    该计划被编译时@Param=0和它仅需要对这个值所以@Param <> 0可以在编译时被评价为false和计划是正确的根本不访问表格。

    enter image description here

    没有OPTION (RECOMPILE)你看这

    EXEC sys.sp_executesql 
        N'SELECT * FROM master..spt_values WHERE @Param <> 0', 
        N'@Param INT', 
        @Param = 0; 
    

    enter image description here

    即使嗅探到的参数值和运行参数值是相同的计划不能被优化到相同的程度因为它将被缓存,并且如果传递了不同的参数值,仍然需要工作。