IN句をEXISTS句へ変換するとパフォーマンスが向上すると言われることがあるので
IN句からEXISTS句への変換例をメモしておきます。
サンプルテーブル
以下の商品テーブル「goods」と属性コードテーブル「type_code」を元に説明します。
IN句を使用したSQL例
商品テーブル「goods」のtype_codeが ‘101’で属性コードテーブル「type_code」にも存在する商品名を取得する例となります。
|
1 2 3 4 |
SELECT tc.code_name FROM type_code AS tc WHERE tc.code IN(SELECT type_code FROM goods WHERE type_code = '101'); |
EXISTS句を使用したSQL例
WHERE句後の「tc.code IN」を「EXISTS」に変更し、「AND type_code = tc.code」を追加しただけです。
|
1 2 3 4 5 |
SELECT tc.code_name FROM type_code AS tc WHERE EXISTS (SELECT 1 FROM goods WHERE type_code = '101' AND type_code = tc.code); |
出力結果(IN句、EXISTS句)
NOT EXISTS句を使用したSQL例
EXISTS句は使い慣れてないと今一つ分かりにくい気がするので、上記のEXISTSをNOT EXISTSで実行してみた例も記載しておきます。なんとなくEXISTSがどういう結果を出力しているかわかるかも。。
|
1 2 3 4 |
SELECT tc.code_name FROM type_code AS tc WHERE NOT EXISTS(SELECT 1 FROM goods WHERE type_code = '101' AND type_code = tc.code); |
出力結果(NOT EXISTS句)
補足
本稿では、 IN句 から EXISTS句 への変換例およびその基本的な使い分けを紹介しましたが、実運用においては以下の点にもご留意ください。
-
データベース製品(たとえば PostgreSQL/Oracle Database/MySQL)やバージョンによって、IN句とEXISTS句の内部実行プランや最適化状況が異なるため、単純に「INは遅い」「EXISTSの方が速い」と一律判断するのは危険です。
-
実際には、サブクエリの対象件数・インデックス構成・統計情報の鮮度などがパフォーマンスに大きく影響します。EXISTSに変えたからといって必ずしも高速化するとは限りません。
-
また、可読性・保守性の観点からは「どちらが読みやすいか・将来変更しやすいか」も考慮に入れるべきです。たとえば、複雑な条件・結合・集計を伴うSQLでは、意図が明確な記述を優先したほうがトラブルを防げます。
-
最後に、SQLのチューニングは「手段」ではなく「目的」—つまり、「実際の業務で期待されるレスポンスタイムを満たしているか」「運用負荷を適切にコントロールできているか」という観点が最も重要です。この点を忘れず、必要に応じて実行計画の確認やプロファイリングを実施してください。
引き続き、SQL設計・実装・運用の改善にお役立ていただければ幸いです。
今後も他の観点(たとえば JOINの最適化/ウィンドウ関数の活用/データ量に対するスケーリング)についても、機会を改めてご紹介したいと思います。
