SQL Server IN と既存のパフォーマンス
-
20-09-2019 - |
質問
以下のどれがより効率的でしょうか?
私はいつも使用する際に少し注意してきました IN
なぜなら、SQL Server は結果セットを巨大なものに変えると信じているからです。 IF
声明。結果セットが大きい場合、これによりパフォーマンスが低下する可能性があります。結果セットが小さい場合、どちらが好ましいかはわかりません。大規模な結果セットの場合はそうではありません EXISTS
より効率的になりますか?
WHERE EXISTS (SELECT * FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)
対
WHERE bx.BoxID IN (SELECT BoxID FROM Base WHERE [Rank = 2])
解決
エンジンがヒットを発見した時点で条件が真であることが判明したとして、それは見て終了しますので、EXISTS
が速くなります。
IN
で、それは更なる処理の前にサブクエリからすべての結果を収集します。
他のヒント
受け入れ答えは近視眼的であり、その中に疑問ビット緩います:
1)いずれも、明示的に被覆率が中に存在するかどうかを言及 左、右、または両側ます。
2)のいずれも考慮に入力左側セットのサイズを取得し、 入力右側のセット。
(質問はちょうど全体の大規模なの結果のセットに言及している)。
私は、オプティマイザが「存在する」対「中」の間で変換することが十分にスマートであると信じて(1)及び(2)、それ以外の場合はそれだけで(例えばに存在するヒントとして使用することができるによる大幅なコスト差があった場合に)右側にシーク可能なインデックスの使用を奨励します。
推定された行数に基づいて(左および右)とインデックス存在左に、右、または両方 -両方の形態が結合順序を逆にし、ループとして実行し、ハッシュまたはマージしている、内部のフォームを結合するために変換することができます。両側ます。
SQL Server 2005 と 2008 でいくつかのテストを行ったところ、他の人が述べているように、EXISTS と IN の両方でまったく同じ実際の実行プランが返されました。オプティマイザーは最適です。:)
ただし、クエリの表現が正しくないと、EXISTS、IN、JOIN は異なる結果を返す場合があることに注意してください。 http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx
私は一緒に行きたいにわたって存する、下のリンクを参照してください。
実行計画は、通常、これらの場合に同一であるとしているが、あなたは、インデックスなどの他のすべての面でオプティマイザの要因は、あなたが本当に知っていることはありませんどのように表示されるまでます。
したがって、IN は EXISTS と同じではなく、同じ実行プランを生成します。
通常、EXISTS は相関サブクエリで使用されます。つまり、EXISTS 内部クエリと外部クエリを JOIN することになります。外部クエリ結合と内部クエリ結合を解決してから、それらの where 句と一致して両方を結合する必要があるため、結果を生成するための手順がさらに追加されます。
通常、IN は内部クエリを外部クエリと関連付けずに使用され、これは 1 ステップのみで解決できます (最良の場合のシナリオ)。
このことを考慮:
IN を使用し、内部クエリの結果が数百万行の異なる値である場合、EXISTS クエリのパフォーマンスが高い (外部クエリと結合するための適切なインデックスがある) ことを考慮すると、EXISTS クエリよりもパフォーマンスが遅くなる可能性があります。
EXISTS を使用し、外部クエリとの結合が複雑な場合 (実行に時間がかかり、適切なインデックスがない場合)、外部テーブルの行数だけクエリが遅くなり、完了までの推定時間が数日かかる場合があります。行数が特定のハードウェアで許容できる場合、またはデータのカーディナリティーが正しい場合 (たとえば、大規模なデータ セット内の DISTINCT 値が少ない場合)、IN は EXISTS よりも高速に実行できます。
各テーブルにかなりの量の行がある場合、上記のすべてが注目されます (「かなり」とは、CPU 処理やキャッシュ用の RAM しきい値を超えるものを意味します)。
したがって、答えは「状況による」です。IN または EXISTS 内に複雑なクエリを作成できますが、経験則として、個別の値を含む行が多数ある場合は、限られた個別の値のセットで IN を使用し、EXISTS を使用するようにしてください。
秘訣は、スキャンする行数を制限することです。
よろしく、
マリアノC
EXISTS
を最適化するために、非常にリテラルです。何かがそこにする必要がありますが、あなたが実際に相関サブクエリから返されたすべてのデータを必要としません。あなただけのブール条件を評価しています。
ですからます:
WHERE EXISTS (SELECT TOP 1 1 FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)
相関サブクエリがRBAR
であるためには、最初の結果ヒットが条件が真なり、それはさらに処理されません。
ここには、非常に賛成票を集めたものを含め、誤解を招く回答がたくさんあります(ただし、彼らの作戦が害を及ぼすことを意味していたと私は信じていません)。 短い答えは次のとおりです。これらは同じです。
(T-)SQL 言語には多くのキーワードがありますが、最終的にハードウェア上で実際に行われるのは、実行クエリ プランに示されている操作だけです。
を呼び出すときに実行するリレーショナル (数学理論) 操作 [NOT] IN
そして [NOT] EXISTS
セミ結合(使用時のアンチ結合)です。 NOT
)。対応する SQL サーバー操作に次のような特徴があるのは偶然ではありません。 同じ名前. 。言及する操作はありません IN
または EXISTS
どこでも - (アンチ)セミのみが参加します。したがって、 論理的に同等であることはあり得ません IN
対 EXISTS
結果を取得する唯一の方法が (アンチ) セミ結合実行操作であるため、選択はパフォーマンスに影響を与える可能性があります。.
例:
クエリ 1 ( プラン )
select * from dt where dt.customer in (select c.code from customer c where c.active=0)
クエリ 2 ( プラン )
select * from dt where exists (select 1 from customer c where c.code=dt.customer and c.active=0)
私の思いつきであり、正しいかどうかは保証されません。この場合、2番目の方が速いと思います。
- 1 つ目では、相関サブクエリにより行ごとにサブクエリが実行される可能性があります。
- 2 番目の例では、相関がないため、サブクエリは 1 回だけ実行する必要があります。
- 2 番目の例では、
IN
一致するものが見つかるとすぐに短絡します。