【问题标题】:Why doesn't exec sp_recompile sometimes not help parameter sniffing?为什么 exec sp_recompile 有时不能帮助参数嗅探?
【发布时间】:2021-07-31 19:05:11
【问题描述】:

我们有一个复杂的存储过程,有时会受到参数嗅探的影响。它是一个大型的“一体式”过程,由系统的许多不同部分调用,因此一个查询计划不适合所有用例是理所当然的。

这很好用,除了周期性地一个特定的报告从几秒到几分钟。过去,快速的exec sp_recompile 会立即加快速度。现在这永远行不通。报告最终会在一两天内“自行修复”,这意味着它需要几秒钟。

重构存储过程目前不是一种选择,我不想执行其他推荐的方法(将参数保存到局部变量、使用重新编译、优化未知),因为据说这些方法有其他副作用。

所以我有这些问题:

  1. exec sp_recompile 为什么不像以前那样加快速度?

  2. 如何判断exec sp_recompile 是否真的清除了查询计划缓存?在执行之前和之后应该运行什么?我尝试了一些来自网络的查询,但无法清楚地判断是否发生了变化,所以如果有一个特定的食谱会很棒。

  3. 使用不同的名称克隆该过程并仅为该报告调用该克隆是否合理?目标是让 SQL Server 为报表缓存单独的计划。但我不确定 SQL Server 是否按过程名称缓存计划,或者它是否缓存存储过程中的各种查询。 (如果是后者,那么这种方法就没用了,因为该过程的任何克隆都会有相同的查询。)

【问题讨论】:

  • 这个过程是由多个带有过程编程的查询组成的,还是只有一个适合所有情况的大查询?
  • “像以前一样”是什么意思 - 究竟是什么?
  • 可能重新编译后立即使用的参数也有问题? “为什么 exec sp_recompile 不像以前那样加快速度?”如果没有查询、表和索引、好的和坏的查询计划、相关参数以及它们如何与表统计信息/直方图相匹配,就不可能知道。所有这些都是您应该做的,而不是我们,因为这是您拥有的信息。如果您不准备重写任何内容,您将不会走得太远:使用sp_recompile 是一种黑客行为,请做好失败的准备
  • 如果您使用了很多 CTE 定义,SQL Server 将尝试构建一个单一的整体执行计划。根据不同的因素,您可能有一个计划编译超时和一个次优计划,对于这些计划,重新编译产生相同或更糟的结果。您可以改为用临时表替换 CTE - 使用中间结果通常具有更好的性能,因为每个查询都使用专用的最佳(或更好)计划单独执行。然后可以进一步对它们进行聚类以删除主查询中的中间排序,并允许优化器也使用统计信息。
  • proc 多久执行一次?如果不是每秒多次,OPTION (RECOMPILE) 可能是一个不错的选择,因为通过优化计划节省的运行时间可能会抵消额外编译成本的副作用。我在厨房水槽查询中取得了很好的成功。

标签: sql-server-2017


【解决方案1】:

使用多个 CTE,尤其是复杂的查询(就像加入视图时一样)可能会导致查询优化器在生成最佳执行计划时出现问题。

如果您使用了很多 CTE 定义,SQL Server 将尝试构建一个单一的整体执行计划,您可能会遇到计划编译超时,从而导致使用次优计划。

您可以将 CTE 替换为临时表 - 使用中间结果通常具有更好的性能,因为每个查询都使用专用的最佳(或至少更好)计划单独执行。这可以帮助优化器对连接和索引的使用做出更好的选择。

如果您可以从两种不同类型的关键参数中受益,理想情况下需要它们自己的最佳计划,那么按照您的建议,您可以选择复制特定于每个用例的过程。

您可以通过使用dm_exec_sql_text 查询您的过程名称来确认这会产生单独的执行计划

select s.plan_handle, t.text
from sys.dm_exec_query_stats s 
cross apply Sys.dm_exec_sql_text(s.plan_handle)t 
where t.text like '%proc name%'

您会注意到每个过程都有不同的plan_handle。

【讨论】:

  • 被接受,因为它提供了一个很好的替代建议,对问题 #3 的确认和一个特定的配方来测试正在创建的两个不同的计划。谢谢。
猜你喜欢
  • 2012-03-05
  • 1970-01-01
  • 2010-10-14
  • 2017-01-30
  • 2014-09-28
  • 2016-10-07
  • 1970-01-01
  • 2015-04-26
  • 1970-01-01
相关资源
最近更新 更多