web-dev-qa-db-ja.com

SQLサブクエリと標準結合を使用する場合

私は不完全に書かれたいくつかのSQLクエリの書き換えに取り組んでおり、それらはサブクエリを過剰に利用しています。サブクエリの使用に関するベストプラクティスを探しています。

任意の助けをいただければ幸いです。

35
Brad Krusemark

サブクエリは、依存サブクエリ相関サブクエリ とも呼ばれます)でない限り、通常は問題ありません。独立したサブクエリのみを使用しており、適切なインデックスを使用している場合は、すぐに実行する必要があります。依存サブクエリがある場合、通常は外部クエリの各行に対して1回実行する必要があるため、パフォーマンスの問題が発生する可能性があります。したがって、外部クエリに1000行ある場合、サブクエリは1000回実行されます。一方、独立したサブクエリは通常、一度だけ評価する必要があります。

従属または独立しているサブクエリが何を意味するのかわからない場合の経験則です。サブクエリを取得し、そのコンテキストから削除し、実行し、結果セットを取得できる場合は、independent subquery

サブクエリの外部のテーブルを参照しているために構文エラーが発生した場合、dependent subquery

もちろん、一般的なルールにはいくつかの例外があります。例えば:

  • 多くのオプティマイザは、従属サブクエリを取得し、JOINとして効率的に実行する方法を見つけることができます。たとえば、NOT EXISTSクエリはANTI JOINクエリプランになる可能性があるため、JOINを使用してクエリを記述するよりも遅くなるとは限りません。
  • MySQLには bug があり、IN式内の独立したサブクエリが依存サブクエリとして誤って識別されるため、次善のクエリプランが使用されます。これは、MySQLの最新バージョンでは明らかに修正されています。

パフォーマンスが問題になる場合は、特定のクエリを測定し、最適なものを確認してください。

52
Mark Byers

ここに特効薬はありません。すべての使用法を個別に評価する必要があります。相関サブクエリが非常に非効率的である場合がありますが、以下の1つはJOINとして記述する方が適切です。

select nickname, (select top 1 votedate from votes where user_id=u.id order by 1 desc)
from users u

一方、EXISTSクエリとNOT EXISTSクエリはJOINよりも優先されます。

select ...
where NOT EXISTS (.....)

通常よりも高速です

select ...
FROM A LEFT JOIN B
where B.ID is null

しかし、これらの一般化でさえ、特定のスキーマとデータの配布については真実ではありません。

6
RichardTheKiwi

残念ながら、答えは使用しているSQLサーバーによって大きく異なります。理論的には、純粋なリレーショナル理論の観点からは結合が優れています。サーバーが内部で正しいことを実行できるようにし、より多くの制御を提供するため、最終的にはより高速になります。 Ifサーバーは適切に実装されています。実際には、サブクエリなどを介してクエリを最適化するように仕向けると、一部のSQLサーバーのパフォーマンスが向上します。

4
Wes Hardaker