小编典典

WHERE-CASE子句子查询性能

sql

该问题可能特定于SQL Server。当我编写查询时,例如:

SELECT * FROM IndustryData WHERE Date='20131231'
AND ReportTypeID = CASE WHEN (fnQuarterDate('20131231')='20131231') THEN  1 
                        WHEN (fnQuarterDate('20131231')!='20131231') THEN  4
                        END;

是否对表的EACH行执行Case内的Case内的函数调用fnQuarterDate(或任何子查询)?

如果我预先在类似这样的变量中获取函数(或任何子查询)的值,会怎么样呢?

DECLARE @X INT
IF fnQuarterDate('20131231')='20131231'
SET @X=1 
ELSE
SET @X=0
SELECT * FROM IndustryData WHERE Date='20131231'
AND ReportTypeID = CASE WHEN (@X = 1) THEN  1 
                        WHEN (@X = 0) THEN  4
                        END;

我知道在MySQL中,如果WHERE子句中的IN(..)内有子查询,则对每一行都执行该子查询,我只想为SQL SERVER查找相同的子查询。

只需填充约3万行的表,然后发现时差:

Query1 = 70ms; 查询2 = 6毫秒。我认为这可以解释它,但仍然不知道其背后的实际事实。

如果不是一个UDF,而是一个简单的子查询,也会有什么区别吗?


阅读 159

收藏
2021-04-14

共1个答案

小编典典

我认为该解决方案在理论上可以帮助您提高性能,但是它也取决于标量函数的实际作用。我认为在这种情况下(我的猜测是将日期格式化为该季度的最后一天)确实可以忽略不计。

您可能需要阅读此页面,并附有建议的解决方法:

http://connect.microsoft.com/SQLServer/feedback/details/273443/the-scalar-
expression-function-would-speed-performance-while-keeping-the-benefits-of-
functions#

因为SQL Server必须在每一行上执行每个函数,所以使用任何函数都会产生游标,如性能下降。

在变通办法中,有一条评论指出

当我在连接列中使用标量UDF时,我遇到了同样的问题,其性能令人震惊。在我用包含UDF结果的临时表替换了UDF并将其用于join子句后,性能提高了几个数量级。MS团队应修复UDF以使其更可靠。

因此看来,是的,这可能会提高性能。

您的解决方案是正确的,但是我建议您考虑对SQL进行改进以使用ELSE,它对我来说看起来更干净:

AND ReportTypeID = CASE WHEN (@X = 1) THEN  1 
                    ELSE 4
                    END;
2021-04-14