【发布时间】:2021-07-31 19:05:11
【问题描述】:
我们有一个复杂的存储过程,有时会受到参数嗅探的影响。它是一个大型的“一体式”过程,由系统的许多不同部分调用,因此一个查询计划不适合所有用例是理所当然的。
这很好用,除了周期性地一个特定的报告从几秒到几分钟。过去,快速的exec sp_recompile 会立即加快速度。现在这永远行不通。报告最终会在一两天内“自行修复”,这意味着它需要几秒钟。
重构存储过程目前不是一种选择,我不想执行其他推荐的方法(将参数保存到局部变量、使用重新编译、优化未知),因为据说这些方法有其他副作用。
所以我有这些问题:
-
exec sp_recompile为什么不像以前那样加快速度? -
如何判断
exec sp_recompile是否真的清除了查询计划缓存?在执行之前和之后应该运行什么?我尝试了一些来自网络的查询,但无法清楚地判断是否发生了变化,所以如果有一个特定的食谱会很棒。 -
使用不同的名称克隆该过程并仅为该报告调用该克隆是否合理?目标是让 SQL Server 为报表缓存单独的计划。但我不确定 SQL Server 是否按过程名称缓存计划,或者它是否缓存存储过程中的各种查询。 (如果是后者,那么这种方法就没用了,因为该过程的任何克隆都会有相同的查询。)
【问题讨论】:
-
这个过程是由多个带有过程编程的查询组成的,还是只有一个适合所有情况的大查询?
-
“像以前一样”是什么意思 - 究竟是什么?
-
可能重新编译后立即使用的参数也有问题? “为什么 exec sp_recompile 不像以前那样加快速度?”如果没有查询、表和索引、好的和坏的查询计划、相关参数以及它们如何与表统计信息/直方图相匹配,就不可能知道。所有这些都是您应该做的,而不是我们,因为这是您拥有的信息。如果您不准备重写任何内容,您将不会走得太远:使用
sp_recompile是一种黑客行为,请做好失败的准备 -
如果您使用了很多 CTE 定义,SQL Server 将尝试构建一个单一的整体执行计划。根据不同的因素,您可能有一个计划编译超时和一个次优计划,对于这些计划,重新编译产生相同或更糟的结果。您可以改为用临时表替换 CTE - 使用中间结果通常具有更好的性能,因为每个查询都使用专用的最佳(或更好)计划单独执行。然后可以进一步对它们进行聚类以删除主查询中的中间排序,并允许优化器也使用统计信息。
-
proc 多久执行一次?如果不是每秒多次,
OPTION (RECOMPILE)可能是一个不错的选择,因为通过优化计划节省的运行时间可能会抵消额外编译成本的副作用。我在厨房水槽查询中取得了很好的成功。
标签: sql-server-2017