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


15

在优化某些存储过程的过程中,我与DBA坐下并经历了一些阻塞和/或读/写活动频繁的存储过程。

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

这是我第一次听说此消息,并且在重新访问我们拥有的所有不同存储过程之前,正在寻求一些确认。他称其为“代码的后期查看”,并且重新编译锁定了解决阻塞的架构。

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

Answers:


18

没有。

这要么很久以前就成为了现实(至少从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重新编译。


3

它不应该有所作为或减少编译锁或减少重新编译的次数,以在堆栈中途或顶部声明一个变量。为了提高可读性,我碰巧经常在顶部执行此操作。

为了弄清问题的“ DBA的想法是什么”,我唯一能想到的(除了Nick认为他们曾经认为过时的观点)可能是他们在谈论参数嗅探(请参阅简单链接上此链接的选项2 )

关于阻塞->如果您看到真正的阻塞,那不是您的DBA最有可能谈论的编译锁争用类型。虽然确实有某些因素会影响到此(例如,不是架构限定表,也不是架构限定存储过程调用),但这肯定不是导致高读取的原因,也可能不是导致阻塞的原因。您绝对应该尽一切可能避免这些编译锁。但是,与担心变量在何处相比,我将调整和优化其余存储过程代码视为更重要的任务。如果要验证自己在这里没有遇到问题,还可以阅读如何识别和解决编译锁

在示例之前/之后发布这些示例,我们将在这里了解DBA的发展方向。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.