优化:将变量声明移至程序顶部

bra*_*d.v 15 sql-server stored-procedures optimization sql-server-2008-r2

在优化一些存储过程时,我与 DBA 坐下来讨论了一些具有高阻塞和/或高读/写活动的存储过程。

DBA 提到的一件事是我应该TABLE在存储过程的顶部声明所有变量(尤其是变量)以避免重新编译。

这是我第一次听说这个,并且在重新访问我们拥有的所有不同存储过程之前正在寻找一些确认。他称其为“延迟查看代码”,而重新编译正在锁定将导致阻塞的模式。

将所有变量声明移到存储过程的顶部是否会减少重新编译?

Nic*_*mas 19

不。

这要么在很久以前是正确的(至少从 SQL Server 2000 起不再是这样),要么从来都不是正确的,您的 DBA 只是将他的建议与以下建议混淆了:

在存储过程开始时将临时表的所有 DDL 语句(如创建索引)组合在一起很重要。通过将这些 DDL 语句放在一起,可以避免由于架构更改而导致的不必要的编译。

您可以在此页面上找到有关此建议背后的推理的另一种解释。

如果我们查看此 Microsoft KB,我们会发现存储过程重新编译的原因可能是以下之一(SQL Server 2005+):

  1. 架构已更改。
  2. 统计数据发生了变化。
  3. 重新编译 DNR。
  4. 设置选项已更改。
  5. 临时表已更改。
  6. 远程行集已更改。
  7. 对于浏览权限已更改。
  8. 查询通知环境已更改。
  9. MPI 视图已更改。
  10. 光标选项已更改。
  11. 带有重新编译选项。

声明一个变量——甚至是一个表变量(即@table_variable)——显然不能触发任何这些事件,因为声明一个变量不算作 DDL。变量(甚至是表变量)是专用于 T-SQL 编程的临时对象。这就是为什么表变量没有统计数据并且不受事务约束的原因声明一个变量(表与否)不能触发 proc 重新编译。

#temp_table然而,创建临时表(即)或索引影响数据库物理定义的 DDL。临时表和索引是具有统计和事务控制的“真实”对象,因此创建它们可以触发上面列表中的任何事件 1、2 或 5,从而触发 proc 重新编译。