【问题标题】:What factors can cause Stored Procedure Recompilation on SQL Server?哪些因素会导致 SQL Server 上的存储过程重新编译?
【发布时间】:2012-01-29 14:55:19
【问题描述】:
我应该注意哪些因素会导致过度的存储过程重新编译?
会导致存储过程重新编译的代码示例会很有用。目的是尽可能避免重新编译,这应该会提高性能。
导致不同输出(根据数据类型和/或列数)的动态 SQL 和变量路径似乎会带来问题。假设是否正确?还有其他例子吗?
编辑:我确实找到了另一个例子。在流控制语句中创建临时表将导致重新编译。
【问题讨论】:
标签:
sql-server
performance
stored-procedures
【解决方案1】:
有几种方法可以确保重新编译存储过程:
- 使用
WITH RECOMPILE,
- 使存储过程动态化(想想
exec())
- 用
sp_recompile 标记要重新编译的proc。
- 更改缓存查询计划所依赖的架构
- 致电
DBCC FREEPROCCACHE
- 在查询级别,可以使用 RECOMPILE 查询提示 (SQL 2008) 重新编译 proc 中的单个语句。
重新编译的因素
除了上面列出的硬因素之外,是什么导致存储过程重新编译?嗯,很多东西。其中一些与上面的列表交织在一起,但我想重新呈现它们,因为它可能并不明显。
- 插入或删除大量数据(索引和表中的数据密度通常控制查询计划)
- 重建索引(对基础对象的更改)
- 创建/删除临时表(同样,基础 DML 更改)。
- 查询计划过期(认为最近没用过,sql想清理内存使用)
这绝不是一份详尽的清单。无论您使用 SQL Server 多久,查询优化器都会不断发展并带来惊喜。但这里有一些可能有用的资源:
但等等 - 还有更多!
话虽如此,您问题中的假设是重新编译总是不利于性能。事实上,经常重新编译是好的。
那么你希望它什么时候重新编译?让我们看一个按姓氏搜索的 proc 示例。存储过程执行 'parameter sniffing' 是一种祝福(如果它对您有用),也是一种诅咒(如果它对您不利)。首先通过某人在Zebr% 上搜索zerbrowski。姓氏索引意识到这是非常具体的,并且会从一百万中返回 3 行——因此构建了一个执行计划。为低行结果编译 proc 后,下一个搜索是 S%。嗯,S 是您最常用的名称,匹配 100 万行中的 93,543 行。
【解决方案2】:
某些 SET 选项可能导致存储过程重新编译,甚至在一次执行中多次重新编译!
其中一些选项甚至可能不在 SP 中
--this will cause recompilation
SET concat_null_yields_null ON;
EXEC spMyProc;
在 SP 内部导致重新编译的一些选项:
阿里萨博特
ANSI_NULLS
QUOTED_IDENTIFIER
幸运的是,这不会导致重新编译:SET NOCOUNT ON;
【解决方案3】:
可选/可变数字参数也可能看起来像重新编译,因为计划是针对特定参数列表缓存的。
如果语句通过连接转换为 SP(希望将来重用),则会提取值并对其进行参数化。
如果这些参数包括调用者动态填充的 IN 子句等内容,则参数列表很少匹配,并且您会看到每次 IN 子句包含不同数量的值时生成的新计划。