質問

リンクされている 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 など) では異なるかどうか知りたいと思っています。

役に立ちましたか?

解決

理論的には、いや、それはどの速くてはなりません。クエリオプティマイザは、同一の実行計画を生成することができるはずです。しかし、いくつかのDBエンジンは、そのうちの一つ(このような単純なクエリのためではなく、複雑に十分なもののために起こりそうではない)のためのより良い実行計画を生成することができます。あなたは両方をテストし、(あなたのDBエンジンに)表示されるはずです。

他のヒント

「JOIN」と「WHERE」のパフォーマンス...すべては、データベース エンジンがクエリをどれだけ最適化できるかにかかっています。返される列にあるインデックスが考慮され、WHERE 句と JOIN 句のパフォーマンスは、物理データベース ファイル自体とその断片化レベル、さらにはデータベース ファイルの保存に使用するストレージ テクノロジによっても左右されることが考慮されます。 。

MSSql サーバーは次の順序でクエリを実行します (これにより、WHERE 句と JOIN 句の機能が理解できるはずです)。

Microsoft SQL Serverクエリの処理順序

以下は、Microsoft SQL Server に関する優れた書籍シリーズからの抜粋です。 Microsoft SQL Server 2005 の内部:T-SQL クエリ どれが見つかるか ここ

(ステップ8) SELECT (ステップ9) DISTINCT (ステップ11)
(ステップ1) から left_table
(ステップ3) 結合タイプ 参加する right_table
(ステップ2)ON 結合条件
(ステップ 4) どこで どこの条件
(ステップ 5) グループ化 リストごとにグループ化
(ステップ 6) [キューブ|ロールアップ] を使用
(ステップ7) 持つ節
(ステップ10) 注文方法 リストごとに注文

正確にターゲット・データベースに制限することなく、これに答えるために方法はありません。

MS-SQLの場合は、両方のクエリが同じ実行計画になりますが、覚えておいてくださいます:

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

WHERE句で結合条件を忘れて、参加厄介なクロスで終わるのは簡単ですので、本当に危険です。

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

これは、実質的に同等であるが、「標準」は、INNER JOIN構文を使用することです。 JOIN構文をOUTERと一致しているとして、それが使用されなければならない主な理由は明快さと機動性を目的としております。

あなたはSQLiteにも使用する場合:。Sqliteを最初にクエリを実行する前にどこ-構文への参加-構文を変換するので、どこ-構文がわずかに速いです。

れません!について具体的にSQLサーバーがあり、それを内側JOIN構文です。かっこいい(個人の意見をアラート!) 読みやすくなり、より明確に意図があり、SQL Server2005年、同等の書式のための外側join.の*=と=*構文によってサポートされていないデフォルトの2005年--に必要なものを互換モードコミュニケーションスキルです。でそれを取り除くと、その次にリリースせる可能性はありません!)

この意味:

  • 切り替える必要性がある場合、クエリから内外の参加が、次のいずれかの操作が必要です書き換えるargh)を速モード(yuk)
  • なgnu emacsモードできないと整合する方法を実装する別の種類の入(インナー対外)、保守悪夢(とを組み合わせて一つのクエリは、行動の非直感的に).

また、合衆に ない 等価です。一部のものはなく、単にできません。Kalen Delaneyの 内部にはSQL Server2000 カバーの一;してお使いいただく場合には、新しい版なので、そのjoin構文は推奨されていません。

明示的には、クエリの意図がより明確であるよう維持するのが容易である合流します。また、彼らは偶然のクロスの対象ではありませんあなたは、クロスクエリで参加している場合ので、メンテナがそれはそこにあることを意図していた知って参加します。

あなたは今までに外部結合を使用する必要がある場合は、

は、* =構文はSQL Serverで廃止され、すぐに削除されることを知っている必要があります。また、それは、現在のすべての時間を予想し、正しい結果が得られない場合がありますので、使用しないでくださいとして機能していません。明示的なアウターを混在させると合流し、句が参加する場所(暗黙の結合)読んで理解するメンテナのためのクエリがはるかに困難になります。

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

私はそれがあまりにも違いはありませんことを推測します。これら2つのクエリの実行計画が同一であるかどうかをチェックすることができます確認します。 MySQLで実行計画を見るためにあなたが文の前に「説明」のキーワードを配置する必要があり、例えばます:

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

私は、同等のはあまりにもMSSQLに存在すると確信しています。

ところで: 私はちょうどnbviewsしたがって、あなたが参加を保存することができ、ドキュメントのテーブルに属性を直接含めると思い1の関係

:これは、このようになりますと、1です。
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top