简体   繁体   English

存储过程中的IF / ELSE性能

[英]IF/ELSE Performance in Stored Procedures

I found this article that explains using IF/ELSE statements in a SP can cause performance deterioration over using separate SPs for each 'branch'. 我发现这篇文章解释了在SP中使用IF / ELSE语句会导致性能下降,而不是为每个“分支”使用单独的SP。 http://sqlmag.com/t-sql/if-statements-and-stored-procedure-performance http://sqlmag.com/t-sql/if-statements-and-stored-procedure-performance

But I have an SP which selects the same columns, from the same tables, and only the WHERE clause changes depending on what variables are present. 但我有一个SP,从相同的表中选择相同的列,只有WHERE子句根据存在的变量而改变。 Here is an example: 这是一个例子:

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

So in this example, is it better to have 2 seperate SPs to handle the different variables or is it ok to have it all in one like this? 所以在这个例子中,最好有2个单独的SP来处理不同的变量,还是可以将它们全部放在这样的一个? (I know using SELECT * is not good practice. I just did it for the sake of example) (我知道使用SELECT *不是很好的做法。我只是为了举例而做了)

Normally, I wouldn't worry about this, although you should look at the white paper referenced by Mikael Eriksson which has a copious amount of useful information on this subject. 通常情况下,我不担心这一点,尽管您应该查看Mikael Eriksson引用的白皮书,该白皮书有关于此主题的大量有用信息。 However, I would remove the Column1 = Column1 statement in the else branch, because that could potentially confuse the optimizer. 但是,我会删除else分支中的Column1 = Column1语句,因为这可能会使优化器混淆。

What the article is referring to is the fact that the stored procedure is compiled the first time it is run. 本文所指的是存储过程在第一次运行时编译的事实。 This can have perverse results. 这可能会产生不正常的结果。 For instance, if the table is empty when you first call it, then the optimizer might prefer a full table scan to an index lookup, and that would be bad as the table gets larger. 例如,如果第一次调用表时表是空的,那么优化器可能更喜欢将全表扫描更改为索引查找,这会因表变大而变坏。

The issue may be that one of the branches gets a suboptimal performance plan, because the data is not typical on the first call. 问题可能是其中一个分支获得了次优的性能计划,因为数据在第一次调用时并不典型。 This is especially true if one of the values is NULL . 如果其中一个值为NULL则尤其如此。 This doesn't only occur with if , but that is one case where you need to be sensitive to the issue. 这不仅发生在if ,而且是您需要对问题敏感的一种情况。

I would recommend the following: 我会推荐以下内容:

  • If your tables are growing/shrinking over time, periodically recompile your stored procedures. 如果您的表随着时间的推移而增长/缩小,请定期重新编译存储过程。
  • If your tables are representative of the data, don't worry about splitting into multiple stored procedures. 如果表格代表数据,请不要担心分成多个存储过程。
  • Your examples should do an index lookup, which is pretty simple. 您的示例应该进行索引查找,这非常简单。 But monitor performance and check execution plans to be sure they are what you want. 但是监控性能并检查执行计划以确保它们是您想要的。
  • You can use hints if you want to force index usage. 如果要强制使用索引,可以使用提示。 (Personally, I have needed hints to force particular join algorithms, but not index usage, but I'm sure someone else has had different experiences.) (就个人而言,我需要提示强制使用特定的连接算法,但不需要索引使用,但我确信其他人有不同的经验。)

For your examples, an index on table1(column1) and table1(column2) should suffice. 对于您的示例, table1(column1)table1(column2)上的索引就足够了。

The summary of the advice is not to fix this until you see there is a problem. 建议的摘要不是在您发现问题之前解决此问题。 Putting the logic into two stored procedures should be for fixing a problem that you actually see, rather than pre-empting problem that may never exist. 把逻辑分为两个存储过程应该是固定 ,你实际看到的,而不是可能永远存在先发制人预问题一个问题。 If you do go with a two-procedure approach, you can still have a single interface that calls each of them, so you still have the same API. 如果您采用双过程方法,您仍然可以使用单个接口来调用每个过程,因此您仍然拥有相同的API。 In other words, the one procedure should become three rather than two. 换句话说,一个程序应该变成三个而不是两个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM