JPAやHibernateのパフォーマンス問題を自動的に検出できるツールがあることを想像してみてください。 Hypersistence Optimizerはそのようなツールです。
はじめに
この記事では、SQL EXISTS 演算子がどのように動作するか、またどのような場合に使用すべきかを見ていきます。
EXISTS 演算子は、SQL 標準の最初の版である SQL:86 から利用できるようになりましたが、別のテーブルで評価された条件に基づいて指定されたテーブルをフィルタリングする際に、SQL のサブクエリ式が実際にどれほど強力であるかを理解していないアプリケーション開発者がまだ多くいることに気づきました。 student
student
id
student_id
student_grade
が子テーブルになります。
student
テーブルには、以下の2つのレコードがあります。
| id | first_name | last_name | admission_score ||----|------------|-----------|-----------------|| 1 | Alice | Smith | 8.95 || 2 | Bob | Johnson | 8.75 |
そして、student_grade
テーブルには、学生が受けた成績が格納されています:
| id | class_name | grade | student_id ||----|------------|-------|------------|| 1 | Math | 10 | 1 || 2 | Math | 9.5 | 1 || 3 | Math | 9.75 | 1 || 4 | Science | 9.5 | 1 || 5 | Science | 9 | 1 || 6 | Science | 9.25 | 1 || 7 | Math | 8.5 | 2 || 8 | Math | 9.5 | 2 || 9 | Math | 9 | 2 || 10 | Science | 10 | 2 || 11 | Science | 9.4 | 2 |
SQL EXISTS
例えば、数学の授業で10点の成績を受けた学生をすべて取得したいとします。
学生の識別子のみに関心がある場合は、次のようなクエリを実行できます。
SELECT student_grade.student_idFROM student_gradeWHERE student_grade.grade = 10 AND student_grade.class_name = 'Math'ORDER BY student_grade.student_id
しかし、アプリケーションは識別子だけでなく、学生のフルネームを表示することに関心があるので、student
テーブルからも情報が必要です。
数学の成績が 10 である student
レコードをフィルタリングするには、次のように EXISTS SQL 演算子を使用します:
SELECT id, first_name, last_nameFROM studentWHERE EXISTS ( SELECT 1 FROM student_grade WHERE student_grade.student_id = student.id AND student_grade.grade = 10 AND student_grade.class_name = 'Math')ORDER BY id
上記のクエリを実行すると、アリスの行だけが選択されていることがわかります。
| id | first_name | last_name ||----|------------|-----------|| 1 | Alice | Smith |
外側のクエリでは、クライアントに返したい student
行の列が選択されています。
EXISTS 演算子は、副問い合わせが少なくとも 1 つのレコードを返す場合は true
false
を返します。 データベースエンジンはサブクエリを完全に実行する必要はありません。 1つのレコードにマッチした場合、EXISTS演算子はtrue
を返し、関連する他のクエリの行が選択されます。
内側のサブクエリは、student_grade
student_id
student
id
列と一致するため、相関関係があります。
SQL NOT EXISTS
成績が9より低い生徒がいない生徒をすべて選択したいと考えてみましょう。 そのためには、EXISTS 演算子の論理を否定する NOT EXISTS を使用します。
したがって、NOT EXISTS 演算子は、基礎となるサブクエリがレコードを返さない場合は true
を返します。 しかし、内部の副問い合わせによって1つのレコードがマッチした場合、NOT EXISTS演算子はfalse
を返し、副問い合わせの実行を停止することができます。
値が9より小さい関連するstudent_grade
student
レコードにマッチさせるには、次のSQLクエリを実行します。
SELECT id, first_name, last_nameFROM studentWHERE NOT EXISTS ( SELECT 1 FROM student_grade WHERE student_grade.student_id = student.id AND student_grade.grade < 9)ORDER BY id
上記のクエリを実行すると、Alice レコードだけがマッチすることがわかります。
オンライン ワークショップ
もしこの記事を楽しんでいただけたなら、今度の4日間のオンライン ワークショップもきっと気に入っていただけると思います。
- High
- High Performance Java Persistence Online Workshop (4時間×4日間)
結論
SQLのEXISTS演算子とNOT EXISTS演算子を使用する利点は、一致するレコードが見つかる限り、内部のサブクエリの実行を停止できることです。
副問い合わせが大量のレコードをスキャンする必要がある場合、1つのレコードがマッチしたらすぐに副問い合わせの実行を停止することで、全体の問い合わせ応答時間を大幅に短縮することができます。
。