第9章(パーサーとオプティマイザー)によると、本のページ172 Sasha Pachevによる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が使用されているためにのみ機能しました。
株価と同様に、クエリとそれを表現しようとすると、制限が適用され、結果が異なる場合があり、過去のパフォーマンスは将来の結果を示すものではありません。