私はそれがひどく遅いことに関係があるとは思わない。潜在的に不正確であることに関係しています。たとえば、次のデータが与えられた場合-個々の顧客または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);
一度も注文したことがないすべての顧客を見つけたいとしましょう。データを考えると、たった1つです。顧客#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
パターンは常に最悪のパフォーマンスを発揮します。
マーティン・スミスは、SOについての彼の回答にも多くの優れた裏付け情報があります。
IN
/NOT IN
が常にネストされたループで実装されると信じているようです。そしてstops SQL Server from creating a ‘plan’
、どういう意味なのか分かりません。