web-dev-qa-db-ja.com

JOINはWHEREよりも高速ですか?

リンクされた2つのテーブルがあると仮定します(一方は他方への外部キーを持っています):

CREATE TABLE Document (
  Id INT PRIMARY KEY,
  Name VARCHAR 255
)

CREATE TABLE DocumentStats (
  Id INT PRIMARY KEY,
  DocumentId INT, -- this is a foreign key to table Document
  NbViews INT
)

これは最も賢いやり方ではありませんが、これは私が思いつく最高の例です。

今、私は500以上のビューを持つすべてのドキュメントを取得したいです。私の頭に浮かぶ2つの解決策は次のとおりです。

SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

または:

SELECT *
FROM Document
INNER JOIN DocumentStats
ON Document.Id = DocumentStats.Id
WHERE DocumentStats.NbViews > 500

両方のクエリは同等ですか、それとも他よりはるかに優れた方法がありますか?もしそうなら、なぜですか?

私の例は完璧ではなく、クエリを調整する必要があるかもしれないことは承知していますが、その点を理解してください;)!

編集:回答で要求されたように、この質問はMSSQLを対象としていましたが、他のDBエンジン(MySQLなど...)と異なるかどうかに興味があります

54
Wookai

理論的には、いや、それ以上速くはならないはずです。クエリオプティマイザーは、同一の実行プランを生成できる必要があります。ただし、一部のDBエンジンは、そのうちの1つに対してより優れた実行計画を作成できます(このような単純なクエリではなく、十分に複雑なクエリに対しては起こりそうにありません)。両方をテストして(DBエンジンで)確認する必要があります。

43
Mehrdad Afshari

ターゲットデータベースに制限せずにこれに正しく答える方法はありません。

MS-SQLの場合、両方のクエリは同じ実行プランになりますが、次のことに注意してください。

SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

WHERE句の結合条件を簡単に忘れてしまい、厄介なクロス結合になってしまうので、本当に危険です。

12
Sam Saffron

少なくともMySQLでは、両方とも同じクエリに最適化されます。

4
Greg

特にSQL Serverについて話している場合は、間違いなくINNER JOIN構文を使用する必要があります。 (個人的な意見の警告!)読みやすく意図が明確であることに加えて、SQL Server 2005の時点では、外部結合に相当する構文はありません。 * =および= *構文は、2005年のデフォルトではサポートされていません。サポートするには、互換モードを有効にする必要があります。最終的には、おそらく次のリリースと同時に削除されます(または削除されない可能性があります!)

これの意味は:

  • クエリを内部結合から外部結合に変更する必要がある場合は、書き換える(argh)か、互換モードを有効にする(yuk)必要があります。
  • 互換モードがないと、さまざまな種類の結合(内部と外部)の実装方法に一貫性がなく、メンテナンスの悪夢(および、2つが1つのクエリに結合される場合、直感的ではない動作)が発生します。

また、一般的な信念に反して、この2つはnotと同等であることに注意してください。あるものはずっと厄介であり、あるものは単に不可能です。 Kalen DelaneyのInside SQL Server 20はいくつかの例をカバーしています。その結合構文はとにかく非推奨であるため、新しいエディションが機能するかどうかはわかりません。

2
Cowan

実際には同等ですが、INNER JOIN構文を使用することは「標準」です。それが使用されるべき主な理由は、OUTER JOIN構文と一貫性があるため、明確さとモビリティの目的のためです。

2
Sev

Sqliteを使用する場合:Sqliteは、クエリを実行する前に最初にjoin-syntaxをwhere-syntaxに変換するため、where-syntaxはわずかに高速です。

2
Theo

違いはないと思います。確かに、これら2つのクエリの説明計画が同一であるかどうかを確認できます。 MySQLのExplainプランを確認するには、ステートメントの前に「explain」キーワードを配置する必要があります。例:

EXPLAIN
SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

MSSQLにも同等のものが存在するはずです。

ちなみに、これは1:1の関係のように見えるので、nbviews属性をDocumentテーブルに直接含めます。したがって、結合を保存できます。

1
samson

MSSQLでは、両方のクエリが同じ実行プランにコンパイルされるため、違いはありません。それは読みやすさについてです-JOINは読みやすいと思うので、それを使用します。

1
SqlRyan