繁体   English   中英

对SQL SERVER查询的微小更改导致执行时间极慢

[英]Minor change to SQL SERVER query causes extremely slow execution time

我不明白这两个查询在功能上有什么不同,这会使它们如此不同。 首先我的初始查询:

SELECT * FROM XSales_Code SC
    WHERE SC.Status = 1
        AND SC.SCode NOT IN
            (
            SELECT DISTINCT SCode FROM XTransactions_01
            WHERE Last_Mdt > '2012-01-01'
                AND SCode IS NOT NULL
            )
        AND SC.Last_Mdt < '2014-01-01'
ORDER BY Last_Mdt desc

执行此过程需要13分6秒。 由于我习惯于像这样简单的查询,所以花了几秒钟而不是几分钟,所以我花了很多时间进行了查询,至少在我看来,这是等效的:

SELECT DISTINCT SCode INTO #TEMP1 FROM XTransactions_01
WHERE Last_Mdt > '2012-01-01'
    AND SCode IS NOT NULL

SELECT * FROM XSales_Code SC
    WHERE SC.Status = 1
        AND SC.SCode NOT IN
            (
            SELECT Scode FROM #TEMP1
            )
        AND SC.Last_Mdt < '2014-01-01'
ORDER BY Last_Mdt desc

DROP TABLE #TEMP1

区别在于此查询需要2秒钟才能执行,而上面的13分钟需要执行2秒钟。 这里发生了什么?

在这两种情况下,您都将使用“相关子查询”,该查询针对XSales_Code中通过Status = 1 AND Last_Mdt < '2014-01-01'条件的每一行执行。

可以这样想: XSales_Code通过Status = 1 AND Last_Mdt < '2014-01-01'过滤,然后SQL Server扫描此中间结果的每一行,并且对于每一行,它都会SELECT DISTINCT SCode FROM XTransactions_01...执行SELECT DISTINCT SCode FROM XTransactions_01...查询以查看是否应包含该行。

您的第二个查询执行关联子查询的次数相同,但是它更快,因为它是针对较小的表执行的。

通常,执行NOT IN查询的最快方法是左联接“ not in”子查询,然后省略左联接列为null的任何行。 这摆脱了相关的子查询。

SELECT * FROM XSales_Code SC
LEFT JOIN (
    SELECT DISTINCT SCode FROM XTransactions_01
    WHERE Last_Mdt > '2012-01-01'
        AND SCode IS NOT NULL
) whatevs ON SC.SCode = whatevs.SCode
WHERE SC.Status = 1
  AND SC.Last_Mdt < '2014-01-01'
  AND whatevs.SCode IS NULL
ORDER BY Last_Mdt desc

这很难解释,但是尝试在没有倒数第二行( AND whatevs.SCode IS NULL )的情况下运行上面的查询,当条件为“ IN”且为空时,您将看到whatevs.SCODE如何具有一个值。条件为“ NOT IN”时。

最后,我想强调一下,相关的子查询并不是天生的邪恶。 通常,它们在IN条件和许多其他用例下都可以正常工作,但在NOT IN条件下,它们往往会变慢。

暂无
暂无

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

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