[英]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.