避けるべきではありませんか?


14

一部のSQL Server開発者の間でNOT INは、非常に遅いと広く信じられている信念であり、クエリは、同じ結果を返すが「悪」キーワードを使用しないように書き換える必要があります。()。

それに真実はありますか?

例えば、使用してクエリの原因となるSQL Serverのいくつかの既知のバグ(バージョンは?)ありますNOT IN使用している同等のクエリよりも悪い実行計画を持っています

  • LEFT JOIN組み合わせNULL小切手または
  • (SELECT COUNT(*) ...) = 0WHERE節?

7
しかし、その記事は非常に不正確です。「In」は、「TableOneの各行に対して同じクエリを何度も実行する必要はありません」。そこのポスターは、IN/ NOT INが常にネストされたループで実装されると信じているようです。そしてstops SQL Server from creating a ‘plan’、どういう意味なのか分かりません。
マーティンスミス

5
@Heinziあなたがリンクしている記事は火事で死ぬはずです、それはナンセンスだらけです。同様:「INを交換するには、我々は内部結合を使用して彼らが効果的に同じものです。」問題は、それらは同じものではないということです。基本的なSQL、つまり結合と半結合の違いを知らない人は、SQL-Serverの動作について分析することを信頼しません。
ypercubeᵀᴹ

回答:


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

一度も注文したことがないすべての顧客を見つけたいとしましょう。データを考えると、たった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についての彼の回答にも多くの優れた裏付け情報があります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.