【MySQL】NOT EXISTSのサブクエリでOR条件を指定すると遅い
3年以上前に Twitter にメモ的に書いたものなのですが、忘れたときに遡って探し出すのが大変なのでこちらに再メモ。
SELECT * FROM tb1 WHERE NOT EXISTS ( SELECT * FROM tb2 WHERE tb2.col1 = tb1.col OR tb2.col2 = tb1.col );
くっそ遅くて、実行計画を見たらテーブル全体を走査する感じになっていました。
次のようにすると改善します。
SELECT * FROM tb1 WHERE NOT EXISTS (SELECT * FROM tb2 WHERE tb2.col1 = tb1.col) AND NOT EXISTS (SELECT * FROM tb2 WHERE tb2.col2 = tb1.col);
このように二つの NOT EXISTS
に分けますが、ここで注意が必要なのが AND
にする点です。
- A
OR
B という条件に該当しない(=A にも B にも該当しない)
↓ つまり
- Aに該当しない
AND
Bにも該当しない
何年も前にその時点の MySQL 最新版でもなく更に古いもので確認して得た知識です。 新しいバージョンではオプティマイザが賢くなって解決している可能性もあります。 ちゃんと自分で実行計画などを確認しながら書きましょう。