【问题标题】:Local Variables in Stored Procedures存储过程中的局部变量
【发布时间】:2023-04-05 13:28:02
【问题描述】:

我在网上看到,如果您在存储过程中使用局部变量而不是输入变量,那么存储过程会被优化,就好像它使用提示 OPTIMIZE FOR UNKNOWN 一样。这到底是怎么发生的?另外,一般来说有什么好的做法:直接使用输入变量或创建局部变量并将输入变量分配给它们?

【问题讨论】:

  • 您能否将minimal reproducible example 包含在实际输出(查询计划)和您认为应该是什么(预期输出)中?你可以使用Paste the Plan
  • 在 Internet 上搜索“参数嗅探”以了解为什么变量的行为类似于 OPTIMIZE FOR UNKNOWN(除非您使用 OPTION(RECOMPILE) 查询提示。就像几乎所有 SQL Server 一样,良好实践的答案是“这取决于”。
  • 非常感谢你们!感谢您的回复。我去看看你们提到的那些文章。
  • 知道“输入变量”被正确地称为参数可能会有所帮助 - 这将使搜索文章变得更加容易。

标签: sql-server t-sql stored-procedures


【解决方案1】:

张贴

来自我的博文Yet Another Post About Local Variables

在存储过程中(甚至在即席查询或动态 SQL,就像上面链接的例子一样),如果你声明一个变量 在该代码块中并稍后将其用作谓词,您将得到 要么是对基数的固定猜测,要么是不太鼓舞人心的 比使用直方图时的估计值。

本文其余部分讨论的局部变量效应产生 与 OPTIMIZE FOR UNKNOWN 提示或 executing queries with sp_prepare 的行为相同。

该估计值将基于表中的行数,并且 列的“所有密度”相乘,对于单个 相等谓词。 multiple predicates 的过程取决于 您正在使用哪种基数估计模型。

你得到的猜测取决于你使用什么样的谓词。

等式谓词将表基数乘以列选择性:

根据您使用的基数估计模型,不等式谓词使用不同的固定百分比的表基数。

【讨论】:

    【解决方案2】:

    正如现有 cmets 中所述,这通常是由于在决定使用什么缓存计划或何时生成新计划时进行参数嗅探。这通常是“应用程序慢,SSMS 快”问题的原因(并不总是原因,而且这不是唯一的症状)。

    Erland Sommarskog 有一个很好的详细但可读的问题概述,当他发现(或人们报告)新的不同边缘情况时会更新,https://www.sommarskog.se/query-plan-mysteries.html
    他包括其他可能的原因、潜在的修复方法以及它们何时可能/无用。 youtube 上还有几个视频,是他在会议和其他活动中谈论这个主题(尽管广度和深度不同),如果您以这种方式更好地理解/保留新信息,您可能希望找到这些视频。

    在使用技巧来强制执行多个计划以避免嗅探问题时要小心的一件事是,在某些情况下,您最终可能会用大量执行相同的示例填充计划缓存,从而导致缓存更多有用计划的空间更少对于您的应用程序的其他部分。你也可以让自己焕然一新 性能问题,每次编译计划比使用不太优化的存储计划浪费更多时间。因此,不要试图通过尝试解释尚未显现的参数嗅探问题的可能性来过早优化,只需在诊断符合这些模式的未来性能问题时牢记这一概念。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-05
      • 2016-04-24
      • 1970-01-01
      • 2021-11-09
      • 2012-10-12
      • 1970-01-01
      相关资源
      最近更新 更多