【问题标题】:Option (recompile) speeds up query execution选项(重新编译)加速查询执行
【发布时间】:2016-10-19 17:49:44
【问题描述】:

将此作为更广泛的问题发布,但如果实际查询有助于解决此问题,请告诉我。

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

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

如果查询在第一个场景中第一次访问服务器,为什么结果会有所不同,因此也应该第一次编译计划?

旁注:

更新 - 添加计划:

【问题讨论】:

  • 这是参数嗅探问题的足迹之一。
  • 如果没有谁知道的查询和计划,可以从parameter embedding optimisation 中受益吗?
  • 如果您将“好”计划与重新编译和“坏”计划进行比较,您应该弄清楚有什么区别。用于编译它的参数在最左边的节点中。

标签: sql-server


【解决方案1】:

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

即使在 bad.sqlplan 中,所有参数的 CompiledValue 和 RunTimeValue 都是相同的

<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

当您使用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 &lt;&gt; 0 可以在编译时评估为 false 并且计划不访问桌子。

没有OPTION (RECOMPILE) 你会看到这个

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

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

【讨论】:

    猜你喜欢
    • 2011-05-15
    • 1970-01-01
    • 2014-11-16
    • 1970-01-01
    • 1970-01-01
    • 2012-09-13
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    相关资源
    最近更新 更多