これら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'
唯一の違いは補足条件の配置です。 1つ目はWHERE
句を使用し、2つ目はON
句に条件を追加します。
Teradataシステムでこれらのクエリを実行すると、Explainプランは同じになり、JOINステップはそれぞれの場合の追加条件を示します。ただし、MySQLに関する this SO question では、結合の作成後にWHERE
処理が発生するため、2番目のスタイルが推奨されるという回答の1つ。
このようなクエリをコーディングする際に従うべき一般的なルールはありますか?それは明らかに私のデータベースに影響を与えないので、プラットフォームに依存している必要があると思いますが、おそらくそれはTeradataの単なる機能です。そして、それがisプラットフォームに依存している場合、いくつかのドキュメント参照を取得してください。何を探すべきか本当にわからない。
本の第9章(パーサーおよびオプティマイザー)のページ172によれば、 Sasha PachevによるMySQLの内部の理解
以下は、次のタスクとしてのクエリの評価の内訳です。
ORDER BY
およびGROUP BY
にキーを使用できるかどうかを確認します。同じページで、次のように書かれています。
MySQLオプティマイザの用語では、すべてのクエリは一連の結合です。ここでは、joinという用語がSQLコマンドよりも広く使用されています。 1つのテーブルのみに対するクエリは、縮退結合です。通常、1つのテーブルからレコードを読み取ることは結合とは考えていませんが、従来の結合で使用されるのと同じ構造とアルゴリズムは、1つのテーブルのみでクエリを解決するために完全に機能します。
存在するキー、データの量、およびクエリの式のため、MySQL結合は時々私たち自身のために(または戻ってくるために)何かを行い、予期しない結果を思い付き、すぐに説明することができません。
以前にこの癖について書いた
Jan 23, 2013
: 入れ子になったUPDATEクエリの問題Feb 22, 2011
: MySQLサブクエリの問題これは、MySQLクエリオプティマイザーがクエリの評価中に特定のキーを破棄する可能性があるためです。
@Philのコメントは、この回答の投稿方法を確認するのに役立ちます(@Philのコメントに+1)
MySQLのクエリオプティマイザーは原始的であるため、@ ypercubeのコメント(これについても+1)は私の投稿のコンパクトバージョンです。残念ながら、それは外部のストレージエンジンを扱っているためでなければなりません。
あなたの実際の質問に関しては、MySQL Query Optimizerは、完了時に各クエリのパフォーマンスメトリックを決定します
おそらく、クエリを書き換える(リファクタリングする)ことにより、実行の順序を強制する必要があります。
ここにあなたが与えた最初のクエリがあります
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計画を変更します。それはより良いまたはより悪い結果を生み出す可能性があります。
株価と同様に、クエリについてそれを表現しようとすると、制限が適用され、結果が異なる場合があり、過去のパフォーマンスは将来の結果を示すものではありません。
Oracleの場合、mySQLには長い説明があったため、オプティマイザを活用する2つの高レベルの方法があります。
まず、ルールベースの最適化(またはRBO)です。 Oracleには15の基本的なルールがあり、構文解析する各クエリは、設定された順序で従おうとします。ルール1から最適化されたクエリを生成できない場合は、ルール2に進み、ルール15に達するまで続行します。
詳細: 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の両方がより少ない条件で結合で実行され、結合から作成された一時テーブルから特定の列をフィルターで除外するため、クエリ1を増やしたいということです。
2つのクエリがあり、それらが同等であると思われる場合、次のことが起こります。
異なる実行計画があります。ここには2つのサブケースがあります。
2.1クエリには異なる実行プランがありますが、どちらのプランも同等に良好に機能します。それも結構です。同等のクエリに対して同じプランを生成する必要はありません。しかし、パフォーマンスは同等でなければなりません。そして、私たちはそれが可能な限り最高であることを願っています。
2.2クエリには異なる実行プランがあり、1つのプランが他のプランよりも優れています。ここでもサブケースがあります:
2.2.1クエリは同等ではないため、計画は異なります。したがって、それらが本当に同等であるかどうかを慎重に確認してください。あなたの場合、それらは本当に同等です。
2.2.2プランは異なりますが、クエリは同等です。これは、オプティマイザが十分に成熟していないことを意味します。完璧なオプティマイザのある完璧な世界では、これは起こらないはずです。つまり、プラットフォームに依存するため、プラットフォーム固有のドキュメントを調べて、これが発生する理由を見つける必要があります。
2.2.3計画は異なり、クエリは同等で、データベースソフトウェアにバグがあります。