我发现这篇文章解释了在 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/