[InterDB] [著者HP] [PREVIOUS][UP][NEXT]

Copyright @ 2009, Suzuki Hironobu @ InterDB


■2-04■ プランナ

プランナの処理は単一テーブルの問い合わせ(Simple Query)と、複数テーブルを結合する問い合わせ(Join Query)で異なります。また、MySQLは問い合わせ計画の列挙の前にWHERE句を簡略化します。

以降、WHERE句の簡略化、単一テーブルの問い合わせ(Simple Query)、および複数テーブルを結合する問い合わせ(Join Query)について解説します。

WHERE句の簡略化

問い合わせ計画の列挙に先立ち、プランナは次に示すWHERE句の簡略化を行います。
(1) 不要なかっこの削除

   ((a AND b) AND c OR (((a AND b) AND (c AND d))))
	→ (a AND b AND c) OR (a AND b AND c AND d)

(2) 定数の折りたたみ

   (a < b AND b = c) AND a = 5	
	→ b > 5 AND b = c AND a = 5

(3) 定数条件の削除

   (b >= 5 AND b = 5) OR (b = 6 AND 5 = 5) OR (b = 7 AND 5 = 6)	
	→ b = 5 OR b = 6

他にもさまざまな最適化が行なわれます。詳細は以下のURLを参照してください。
http://dev.mysql.com/doc/refman/5.1/ja/where-optimizations.html

単一テーブルの問い合わせ(Simple Query)

単一テーブルの問い合わせの場合は、次に示す検索方式のうち、最適なものを選択します。検索方式は効率の良い順に列挙しています(【表.2-2】参照)。

表.2-2 Simple Queryの処理に使われる検索方式
検索方式説明
systemテーブルが1行だけの場合に選択。
const主キー(PRIMARY KEY)、もしくはインデックス(INDEX)と一意性(UNIQUE)制約の設定された列rowに対し、条件"WHERE row = 定数"がある場合に選択。
対象となる行が1行しかないと保証されているため、インデックスを直接選択できる。よって非常に高速にデータにアクセスできる。
refインデックスが設定された列rowに対し、条件"WHERE row = 定数"がある場合に選択。
インデックスを直接選択し、そこから(ひとつ、もしくは複数の)テーブルデータを参照する。
ref_or_nullrefとほぼ同様で、条件にNULLの場合を加えた場合に選択。
具体的には、インデックスが設定された列rowに対し、条件"WHERE row = 定数 OR row IS NULL"がある場合に選択。
index_merge複数のrangeスキャンする行を結合する場合に選択。
インデックスを張った行idx1とidx2について、"WHERE idx1 = 定数 OR idx2 = 定数"がある場合に使われる。
unique_subquery"value IN (SELECT primary_key FROM table WHERE expr)"の形式で(INサブクエリでなく)refを選択。
index_subquery"value IN (SELECT idx FROM table WHERE expr)"の形式で(INサブクエリでなく)refを選択。
unique_subqueryとの違いは、主キーでなく任意のインデックスを張った行であること。
range インデックスが設定された列rowに対し、WHERE句で範囲指定した場合に選択。指定された範囲のインデックスを順に選択し、インデックス毎にテーブルデータを参照する。
index (全ての)インデックスを順に選択し、インデックス毎にテーブルデータを参照する。
ALL全てのテーブルデータを順に検索する(シーケンシャルスキャン)。

エクゼキュータの処理については2-05をご覧ください。
複数テーブルを結合する問い合わせ(Join Query)

SELECT文に複数テーブルの結合がある場合には、結合条件の処理順序を考慮しつつ、次に示す検索方式による実行可能な計画を列挙します。
複数テーブルの結合では`eq_ref'という検索方式が加わります。検索方式は効率の良い順に列挙しています(【表.2-3】参照)。
表.2-3 Join Queryの処理に使われる検索方式
検索方式説明
system前述
const前述
eq_ref主キー(PRIMARY KEY)制約の設定された列rowに対し、条件"WHERE row = const"がある場合に選択。
ref前述
ref_or_null前述
index_merge前述
unique_subquery前述
index_subquery前述
range前述
index前述
ALL前述

例えば、テーブルt1とt2を結合する場合、テーブル毎に結合方式が10方式、処理順序(テーブルt1を先に処理するか、t2を先にするか)を考慮すると、200通りの組合せが考えられます(補足 1)。

しかし、例えば2行以上データがある場合に`system'は無意味ですし、インデックスが設定されていなければ`ALL'しか選択できません。
また例えば、WHERE句による制約が``WHERE row < 10''のような範囲指定の場合は、`range', `index',`ALL'のいずれかしか選択できません。

このように、テーブルや結合条件によって明らかに無意味な結合方式が必ずあるので、実際に列挙される問い合わせ計画の数はかなり少なくなります。


こうして列挙された問い合わせ計画のうち、テーブルの行数やインデックス情報などを基に、最も効率良く処理できる(とプランナが判断した)問い合わせ計画を、エクゼキュータが処理します(補足 2)。
エクゼキュータの処理については2-05をご覧ください。


補足


(1)
正確には、使用可能なインデックスの数も考慮しなければなりません。

(2)
`インデックス情報'の更新はANALYZE TABLE文で行います。



[PREVIOUS][UP][NEXT]