
existsが遅いときの対処法
existsを使用したクエリは行数が増えると遅くなります。
もちろんnot exstsにした場合も同様です。
そこで、遅くなった時にどのように高速化するかについて紹介します。
目次
existsが遅いときの対処法
結論を先に述べますと
- exists を高速化するには inner joinへ変更
- not exists を高速化させるには left join へ変更
です。
まずは高速化したいexistsのクエリのテーブル構造です。
ユーザーテーブルに対して存在チェックする注文テーブルです。


続いてexistsのクエリです。
この「存在」チェックのクエリを高速化するにはinner joinを用います。
「存在しない」チェックの場合はleft joinを使用します。
left joinの特性として、結合できなかった列はnullになる性質をもっています。
そこに、「is null」を使用して「存在しない」を判定しています。
existsクエリをjoin句に変換するときは1対1にする
存在する/しない チェックの注意点は1対多になっていることが多いことです。
ですので、抽出データの重複を避けて存在チェックを1対1にするために、先に集計します。
今回はユーザー単位で存在チェックをしたいので、注文テーブルはuser_idでグループ化しています。
existsが遅いのはレコードをみる回数が多いから
existsのイメージとしてはユーザーテーブルの1レコードに対して注文テーブルすべてを結合させるイメージです。
つまり、ユーザーテーブルが1000レコードあり、注文テーブルが1万レコードならば、最大で1000万になります。
掛け算ゆえに、existsあるいはnot existsを用いたクエリはレコードが増えると劇的に遅くなります。
(おまけ)存在チェック用のjoinにはコメントを入れてわかりやすく
別の人が読んだときにわかるように、簡単でよいのでコメントを入れることをお勧めします。
というのも、「select句に使用しない結合」になるので、
パッと見て「何故結合しているか」がわかりにくくなるためです。
おわりに
数百、数千程度ではexistsの速度低下は気にならないことが多いです。
ただ、大量のデータに対してexsitsをクエリに使用すると速度が急激に低下します。
ですので、最初からinner joinもしくはleft joinでクエリを作るのはアリだと思います。