不应该避免吗?

Hei*_*nzi 14 performance sql-server except query-performance

在一些 SQL Server 开发人员中,普遍认为NOT IN速度非常慢,应该重写查询,以便它们返回相同的结果,但不要使用“evil”关键字。(示例)。

这有什么道理吗?

例如,SQL Server 中是否存在一些已知错误(哪个版本?)导致使用NOT IN的查询比使用的等效查询具有更差的执行计划

  • 一个LEFT JOIN结合了NULL支票或
  • (SELECT COUNT(*) ...) = 0WHERE条款中?

Aar*_*and 14

我认为这与非常慢没有任何关系。它与潜在的不准确有关。例如,给定以下数据 - 可以由个人客户或 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);
Run Code Online (Sandbox Code Playgroud)

假设我想找到所有从未下过订单的客户。给定数据,只有一个:客户#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;
Run Code Online (Sandbox Code Playgroud)

结果:

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);
Run Code Online (Sandbox Code Playgroud)

现在,还有一些性能问题,我在这篇博文中讨论了这些问题。根据数据和索引,NOT EXISTS通常会优于NOT IN,我不知道它是否会表现得更糟。您还应该注意,EXCEPT可以引入不同的排序操作,因此您最终可能会得到不同的数据(同样,取决于来源)。而且流行的LEFT OUTER JOIN ... WHERE right.column IS NULL模式总是表现最差的。

Martin Smith 在他对 SO 的回答中也有很多很好的支持信息