不应该避免吗?


14

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

这有什么道理吗?

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

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

7
那篇文章非常不准确。“输入”不必“必须为TableOne中的每一行一遍又一遍地运行相同的查询”。那里的发布者似乎相信IN/ NOT IN将始终使用嵌套循环来实现。我也不知道这stops SQL Server from creating a ‘plan’意味着什么。
马丁·史密斯

5
@Heinzi您链接到的那篇文章应该死于大火,这是胡说八道。就像:“要替换IN,我们使用INNER JOIN。它们实际上是同一回事。” 问题是,它们不是一回事。我不相信一个不了解基本SQL的人来分析有关SQL Server行为的任何信息,即连接和半连接之间的区别。
ypercubeᵀᴹ

Answers:


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);

假设我要查找从未下过订单的所有客户。给定数据,只有一个:客户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的回答中也有很多很好的支持信息

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.