存储过程中的IF / ELSE性能

时间:2014-08-17 14:30:44

标签: sql sql-server stored-procedures

我发现这篇文章解释了在SP中使用IF / ELSE语句会导致性能下降,因为每个“分支”使用单独的SP。 http://sqlmag.com/t-sql/if-statements-and-stored-procedure-performance

但我有一个SP,从同一个表中选择相同的列,只有WHERE子句根据存在的变量而改变。这是一个例子:

IF @Variable1 IS NOT NULL 
 BEGIN
   SELECT 
        *
   FROM
     dbo.Table1
   WHERE
     Column1 = @Variable1
  END
ELSE IF @Variable1 IS NULL AND @Variable2 IS NOT NULL
 BEGIN
  SELECT 
   *
  FROM
   dbo.Table1
  WHERE
   Column1 = Column1 
   AND
   Column2 = @Variable2
 END

所以在这个例子中,最好有两个单独的SP来处理不同的变量,还是可以将它们全部放在这样的一个? (我知道使用SELECT *并不是一种好的做法。我只是为了举例而做的)

1 个答案:

答案 0 :(得分:4)

通常情况下,我不会担心这一点,尽管你应该看一下Mikael Eriksson引用的白皮书,该白皮书有关于这个主题的大量有用信息。但是,我会删除Column1 = Column1分支中的else语句,因为这可能会使优化器混淆。

本文所指的是存储过程在第一次运行时编译的事实。这可能会产生不正常的结果。例如,如果第一次调用表时该表为空,那么优化器可能更喜欢将全表扫描更改为索引查找,这会因表变大而变坏。

问题可能是其中一个分支获得了次优的性能计划,因为数据在第一次调用时并不典型。如果其中一个值为NULL,则尤其如此。这不仅发生在if,而且这是您需要对问题敏感的一种情况。

我会推荐以下内容:

  • 如果您的表随着时间的推移而不断增长/缩小,请定期重新编译存储过程。
  • 如果您的表格代表数据,请不要担心分成多个存储过程。
  • 您的示例应该进行索引查找,这非常简单。但是监控性能并检查执行计划以确保它们是您想要的。
  • 如果要强制使用索引,可以使用提示。 (就个人而言,我需要提示强制使用特定的连接算法,但不需要索引使用,但我确信其他人有不同的经验。)

对于您的示例,table1(column1)table1(column2)上的索引就足够了。

建议的摘要不是在您发现问题之前解决此问题。将逻辑放入两个存储过程应该是修复您实际看到的问题,而不是预先解决可能永远不存在的问题。如果您采用双过程方法,您仍然可以使用单个接口来调用每个过程,因此您仍然拥有相同的API。换句话说,一个程序应该变成三个而不是两个。