BBH
-Biz Branding Hub-
投稿日 : 
2019/12/20
更新日 : 
2019/12/20

【SQL】「INよりEXISTSを使った方がインデックスが使用されるので早い」について解説

SQLにおいて、しばしば
「INよりEXSITSを使った方がインデックスが使用されるので性能がでる」
ということが言われます。
これについて、なぜそう言ったことが言えるのかを解説していきます。

テーブルAとテーブルBのあるカラムを比較し、テーブルAにもテーブルBにも存在する値のみを抽出するSQLを考えていきます。
INとEXISTSを使ったパターンはそれぞれ以下のようになります。

INを使ったパターン

SELECT *
From table_a
WHERE col IN (
  SELECT col
  FROM table_b
);

EXISTSを使ったパターン

SELECT *
From table_a
WHERE col EXISTS (
  SELECT *
  FROM table_b
  WHERE table_a.col = table_b.col
);

この場合、一般的にEXISTSを使用した後者のクエリの方が早くなります。
この理由をそれぞれのクエリがどのように実行されるのかを見ることで解明していきましょう。

INを使ったパターンの挙動

INの場合、まずサブクエリが実行されます。
table_bからすべてのcolの値を検索している部分ですね。
この結果が一時的にDBのメモリにワークテーブルとして展開されます。

次に外側のクエリが実行されます。
table_a中に存在するcolが、先ほど作成したワークテーブルの中に存在するかを検索します。
この際、ワークテーブルにはインデックスが貼られません。
そのため、ワークテーブル内をフルスキャンすることになります。
ワークテーブルの行数が多ければ多いほど実行に時間がかかることがわかります。

EXISTSを使ったパターンの挙動

EXISTSを使った場合も同様にサブクエリが実行されます。
ただし、この際行われるのは、現在みているtable_aのcolと同じcolを持つtable_bのレコードが存在するかです。
この処理は、table_bのインデックスが使用されるので、インデックススキャンが行われます。
table_bの行数にもよりますが、一般的にはフルスキャンよりも高速になります。
(table_bのcolにインデックスが作成されている前提となります。)

実際の挙動は実行計画を確認しよう

一般的にこの二つのSQLは上記のような動作をします。
しかし、これはあくまで一般的であり、DBMSやオプティマイザの仕様によって微妙に異なってきます。
なので、実際にどのような挙動を取っているかは実行計画を確認するようにしましょう。

Profile

管理人プロフィール

都内でITエンジニアをやってます。
変遷:中規模SES→独立系SIer→Webサービス内製開発
使用技術はその時々でバラバラですが、C#、AWSが長いです。
どちらかと言うとバックエンドより開発が多かったです。
顧客との折衝や要件定義、マネジメント(10名弱程度)の経験あり。
最近はJava+SpringBootがメイン。

Recommend