Jan 16, 2012

MySQLで高速処理するSELECT文の書き方案

(1)LEFT JOINとRIGHT JOINは、必要の無い限り使わない

LEFT/RIGHT JOINは、JOINする相手(RIGHT/LEFT)にないレコードを結果セットに残す機能。

MySQL 5.1 リファレンスマニュアル 6.2.11. 外側Join 単純化
では、
「オプティマイザが外側joinオペレーションのjoinクエリ計画を評価する際、各オペレーション時、外側テーブルが内側テーブルより前にアクセスされます。そのようなプランは、入れ子ループスキーマによる外側joinオペレーションを含むクエリの実行のみ可能なため、オプティマイザ選択肢は制限されています。」
と書いてある。

外側joinとは、LEFT JOINとRIGHT JOINのことである。

(2)INNER JOINのON節は、使わずWHERE節で条件を指定してよい。

MySQL 5.1 リファレンスマニュアル 6.2.11. 外側Join 単純化
では、
「T1 INNER JOIN T2 ON P(T1,T2)フォームの全ての内側join表現は T1,T2、P(T1,T2)結合されたWHERE条件によって置き換えられます。(あるいは、組み込まれたjoinのjoin条件が存在する場合は、それに置き換えられます)。」
と書いてある。

苦労してON節を書く、つまり構文を覚える必要はない。

(3)あとはMySQLオプティマイザに任せる

MySQLオプティマイザは、かなり賢いらしいが詳細が不明

以下は、推測

(4)FROM節で絞込み効果のあるテーブルを先に書く

理由:
- MySQLオプティマイザはどのテーブルから処理するか明言していないが、判断に困れば先に書いてあるテーブルを外部のFOR-LOOPで処理するらしい

(5)WHERE節では、できるだけ、トップレベルの結合をAND結合とする式にする

良い例: WHERE ( 式1 AND 式2 AND 式3 )

- ここで式1内部に OR が、あってもよい。

悪い例: WHERE ( 式X OR  式Y OR 式Z )

理由:

- MySQLオプティマイザの判断が容易になる
- AND結合なら評価順(テーブルFOR-LOOPの内外への移動)を簡単に変更できる。
- 対象レコードの絞込みが設計者にとって考え易い、


(6)WHERE節では、絞込み効果のある式を先に書く

 AND結合にした後での話であるが、MySQLオプティマイザが判断に困れば先に書いてある式を優先利用するらしいから

(7)OR結合なら、成立しやすい式を先に書く


(8)ネストするSELECTは書かなくてもよい。


どうも、レコードルーブが二回になると大概は遅いらしい。MySQLオプティマイザはネストを解消してから処理を始めようとするらしい。

ということで、早くなると信じて苦労してネストするSELECTは書く必要がなさそう。