JOIN条件とWHERE条件の実行に違いはありますか?


17

これら2つのクエリ例の間にパフォーマンスの違いはありますか?

クエリ1:

select count(*)
from   table1 a
join   table2 b
on     b.key_col=a.key_col
where  b.tag = 'Y'

クエリ2。

select count(*)
from   table1 a
join   table2 b
on     b.key_col=a.key_col
   and b.tag = 'Y'

唯一の違いは補足条件の配置であることに注意してください。最初はWHERE句を使用し、2番目は条件をON句に追加します。

Teradataシステムでこれらのクエリを実行すると、Explainプランは同一であり、JOINステップはそれぞれの場合に追加の条件を示します。しかし、MySQLに関するこのSOの質問では、回答の1つはWHERE、結合が行われた後に処理が行われるため、2番目のスタイルが好ましいことを示唆しています。

このようなクエリをコーディングする際に従うべき一般的なルールはありますか?データベースに明らかに影響を与えないため、プラットフォームに依存する必要があると思いますが、おそらくそれはTeradataの単なる機能です。また、プラットフォームに依存する場合、いくつかのドキュメントリファレンスを入手してください。何を探すべきか本当に分かりません。


9
RDBMSesオプティマイザーが構文解析と最適化をどのように扱うかに依存するため、プラットフォームに依存します。
フィリー

8
そして、リンクされた質問のその答えは、いくつかのダウン票に値します。MySQLのプリミティブオプティマイザーでさえ、これらの単純なクエリは同等であり、「すべての結合が行われた後にWHERE句が評価される」ことは、実際の実行ではなく論理レベルでのみ正しいことを理解します。
ypercubeᵀᴹ

1
実際には複製ではありません。その質問と答えは、「暗黙的な」対「明示的な」JOIN構文を比較していました。補足的な結合条件について具体的に尋ねています。
ベルビュー

以前に試してみて、多くの反対票を得たので、回答をあえて投稿するつもりはありません。多くの結合がある場合、条件を結合に持ち込んで、より良いクエリプラン(早期にフィルター処理された)になった経験がある場合があります。それでも同じ結果。
パパラッチ

回答:


14

第9章(パーサーとオプティマイザー)によると、本のページ172 Sasha PachevによるMySQL内部の理解

MySQL内部の理解

以下は、次のタスクとしてのクエリの評価の内訳です。

  • テーブルからレコードを取得するために使用できるキーを決定し、各テーブルに最適なキーを選択します。
  • 各テーブルについて、キーを読み取るよりもテーブルスキャンの方が優れているかどうかを判断します。キーの値に一致するレコードが多数ある場合、キーの利点が減り、テーブルスキャンが高速になります。
  • クエリに複数のテーブルが存在する場合、テーブルを結合する順序を決定します。
  • WHERE句を書き直してデッドコードを排除し、不要な計算を減らし、可能な限り制約を変更して、キーの使用方法を開きます。
  • 未使用のテーブルを結合から削除します。
  • ORDER BYおよびにキーを使用できるかどうかを判断しますGROUP BY
  • サブクエリを簡素化し、結果をキャッシュできる範囲を決定します。
  • ビューのマージ(ビュー参照をマクロとして展開)

同じページで、次のように表示されます。

MySQLオプティマイザーの用語では、すべてのクエリは結合のセットです。ここで、結合という用語は、SQLコマンドよりも広く使用されています。1つのテーブルのみに対するクエリは、縮退結合です。通常、1つのテーブルからのレコードの読み取りを結合とは考えませんが、従来の結合で使用されるのと同じ構造とアルゴリズムは、1つのテーブルのみでクエリを解決するために完全に機能します。

エピローグ

存在するキー、データの量、クエリの式のために、MySQL Joinsは時々私たち自身のために(または私たちに戻るために)物事を行い、予期しない結果をすぐに説明できません。

前にこの癖について書いた

MySQL Query Optimizerは、クエリの評価中に特定のキーを削除できるためです。

@Philのコメントは、この回答の投稿方法を確認するのに役立ちます(@Philのコメントに対して+1)

MySQLのクエリオプティマイザーはプリミティブであるため、@ ypercubeのコメント(これについても+1)は私の投稿のコンパクトバージョンです。残念ながら、それは外部ストレージエンジンを扱うためでなければなりません。

結論

実際の質問に関しては、MySQLクエリオプティマイザーは、実行された各クエリのパフォーマンスメトリックを決定します

  • 行を数える
  • キーを選択する
  • 断続的な結果セットのマッサージ
  • そうそう、実際に参加しよう

おそらく、クエリを書き換える(リファクタリングする)ことによって実行順序を強制する必要があります。

これはあなたが与えた最初のクエリです

select count(*)
from   table1 a
join   table2 b
on     b.key_col=a.key_col
where  b.tag = 'Y';

最初にWHEREを評価するように書き直してください

select count(*)
from   table1 a
join   (select key_col from table2 where tag='Y') b
on     b.key_col=a.key_col;

それは間違いなくEXPLAINプランを変えるでしょう。それはより良いまたはより悪い結果を生み出す可能性があります。

このテクニックを適用したStackOverflowの質問に一度答えました。EXPLAINは恐ろしいものでしたが、パフォーマンスはダイナマイトでした。正しいインデックスが存在し、サブクエリでLIMITが使用されているためにのみ機能しました

株価と同様に、クエリとそれを表現しようとすると、制限が適用され、結果が異なる場合があり、過去のパフォーマンスは将来の結果を示すものではありません。


2
MySQL固有の詳細情報、特に「エピローグ」と「結論」の違いを学ぶように私をだますために+1!
ベルビュー

私の投稿では、エピローグはサブ結論です。
RolandoMySQLDBA

6
@Rolando:最新のMariaDB(5.3および5.5)バージョンおよび最近リリースされたメインのMySQL(5.6)バージョンのオプティマイザーの改善についてAftermathを追加できます。これにより、一部の書き換えが不要になる場合があります。
ypercubeᵀᴹ

1

Oracleの場合、mySQLには長い説明があったため、オプティマイザーを活用する2つの高レベルの方法があります。

1つ目は、ルールベースの最適化(またはRBO)です。Oracleには、解析する各クエリが設定された順序で従おうとする15の定石ルールがあります。ルール1から最適化されたクエリを生成できない場合、ルール15に到達するまでルール2に進みます。

詳細情報:https : //docs.oracle.com/cd/B10500_01/server.920/a96533/rbo.htm

これらは、Cost Based Optimizer(別名CBO)に変換されていない11.1以下のOracle RDBMSカーネルに影響します。Oracle 11.2以降ではCBOオプティマイザーが必要ですが、ユーザーが必要に応じて特定のSql IDを古いRBOメソッドで強制的に最適化できます。

代わりに、Oracle 11.1+のCBOは、同じSQL IDに対して複数の実行計画を作成し、全体の予想コストが最も低い実行計画を実行します。RBOの多くのロジックを活用しますが、テーブル統計を分析して、エンドユーザーにデータを提供するためにDBが行わなければならない各操作の動的実行計画コストを作成します。非常に大きなテーブルで全テーブルスキャンを実行すると、本当にコストがかかります。10行のテーブルで全テーブルスキャンを実行するのは安価です。RBOでは、これらは同等の操作と見なされていました。

詳細情報:https : //oracle-base.com/articles/misc/cost-based-optimizer-and-database-statistics

特定のクエリの例:Oracleは、情報を解析して異なる実行計画を作成する可能性が高いため、一方は他方よりも技術的に優れています。ただし、これはわずかな違いです。Oracle RBOとCBOの両方は、より少ない条件で結合を実行し、結合から作成した一時表から特定の列を除外するため、Oracle RBOとCBOのどちらもクエリ1を好むでしょう。


1

2つのクエリがあり、それらが同等であると考える場合、次のことが起こります。

  1. 両方のクエリの実行計画は同じです。それは素晴らしいことであり、それは私たちが期待することです。これがクエリの最適な実行プランであることを期待しましょう。
  2. さまざまな実行計画があります。ここには2つのサブケースがあります。

    2.1クエリの実行プランは異なりますが、両方のプランのパフォーマンスは同等です。それも結構です。同等のクエリの場合、同じプランを生成する必要はありません。しかし、パフォーマンスは同等でなければなりません。そして再び、それが可能な限り最高であることを願っています。

    2.2クエリには異なる実行計画があり、1つの計画が他の計画よりも優れています。繰り返しますが、サブケースがあります。

    2.2.1クエリは同等ではないため、計画は異なります。したがって、それらが本当に同等であるかどうかを慎重に確認してください。あなたの場合、それらは本当に同等です。

    2.2.2計画は異なりますが、クエリは同等です。これは、オプティマイザーが十分に成熟していないことを意味します。完璧なオプティマイザーのある完璧な世界では、これは起こりません。そう、それはプラットフォームに依存しているので、プラットフォーム固有のドキュメントを調べて、なぜこれが起こるのかを知る必要があります。

    2.2.3計画は異なり、クエリは同等であり、データベースソフトウェアにはバグがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.