sql - 存储过程中的 IF/ELSE 性能

标签 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

所以在这个例子中,是用 2 个独立的 SP 来处理不同的变量更好,还是像这样将所有的 SP 都放在一个中更好? (我知道使用 SELECT * 不是一个好习惯。我这样做只是为了举例)

最佳答案

通常情况下,我不会担心这个问题,尽管您应该查看 Mikael Eriksson 引用的白皮书,其中包含有关此主题的大量有用信息。但是,我会删除 else 分支中的 Column1 = Column1 语句,因为这可能会使优化器感到困惑。

本文所指的是存储过程在第一次运行时被编译。这可能会产生不良结果。例如,如果第一次调用时表是空的,那么优化器可能更喜欢全表扫描而不是索引查找,随着表变大,这会很糟糕。

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

我会推荐以下内容:

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

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

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

关于sql - 存储过程中的 IF/ELSE 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25350124/

相关文章:

c# - 如何在 C# 中创建与 Mysql 的全新连接?

sql-server - SQL Server代理作业自定义错误消息

sql - 查找特定字符和/或字符串 SQL Server 2008

sql-server - 如何使用 VB Net 将数据插入 SQL Server

.net - 无法在我的 Entity Framework v4 + POCO :( 中使用存储过程

mysql - 一些变量保持为空 - 存储过程MySQL

mysql "IN"运算符删除几行或几条查询?哪个更快?

sql - PostgreSQL 将列类型从 DATERANGE 更改为 TSTZRANGE 并迁移数据

sql - (SQL) 关系设计问题

PHP MySQL 插入查询,如果已经存在则不会插入