我认为这与缓慢的速度无关。这与可能不准确有关。例如,给定以下数据-可以由单个客户或B2B合作伙伴下达的订单:
DECLARE @Customers TABLE(CustomerID INT);
INSERT @Customers VALUES(1),(2);
DECLARE @Orders TABLE(OrderID INT, CustomerID INT, CompanyID INT);
INSERT @Orders VALUES(10,1,NULL),(11,NULL,5);
假设我要查找从未下过订单的所有客户。给定数据,只有一个:客户2。我可能会通过以下三种方式编写查询来查找该信息(还有其他信息):
SELECT [NOT IN] = CustomerID FROM @Customers
WHERE CustomerID NOT IN (SELECT CustomerID FROM @Orders);
SELECT [NOT EXISTS] = CustomerID FROM @Customers AS c
WHERE NOT EXISTS (SELECT 1 FROM @Orders AS o
WHERE o.CustomerID = c.CustomerID);
SELECT [EXCEPT] = CustomerID FROM @Customers
EXCEPT SELECT CustomerID FROM @Orders;
结果:
NOT IN
------
-- <-- no results. Is that what you expected?
NOT EXISTS
----------
2
EXCEPT
------
2
现在,也存在一些性能问题,我将在此博客文章中讨论这些问题。取决于数据和索引,它们NOT EXISTS
通常会胜过NOT IN
,并且我不知道它是否会表现更差。您还应注意,这EXCEPT
可能会引入不同的排序操作,因此最终可能会得到不同的数据(再次取决于源)。而且流行的LEFT OUTER JOIN ... WHERE right.column IS NULL
模式始终是表现最差的。
马丁·史密斯(Martin Smith)在关于SO的回答中也有很多很好的支持信息。
IN
/NOT IN
将始终使用嵌套循环来实现。我也不知道这stops SQL Server from creating a ‘plan’
意味着什么。