WHERE
の最適化は、ほとんどの場合
SELECT
とともに使用されるため、SELECT
部分に適用されますが、DELETE
や
UPDATE
のステートメントの
WHERE
にも同じ最適化が適用されます。
また、このセクションは完全なものではないため、注意が必要です。MySQL は多様な最適化を実行するため、すべてを文書化するには時間が足りませんでした。
MySQL によって実行される最適化の一部をここに紹介します。
不要なかっこの削除。
((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)
定数の折りたたみ。
(a<b AND b=c) AND a=5 -> b>5 AND b=c AND a=5
定数条件の削除(定数の折りたたみに必要)。
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6) -> B=5 OR B=6
インデックスが使用する定数式が評価されるのは、1 回に限られる。
WHERE
がない単一テーブルの
COUNT(*)
は、MyISAM
と HEAP
テーブルのテーブル情報から直接取り出される。
これは、テーブル 1
つのみで使用する場合はすべての NOT
NULL
式でも実行される。
無効定数式の早期検出。MySQL は実行不可能な
SELECT
ステートメントがある場合、それを迅速に検出し、結果としてレコードを返さない。
GROUP BY
またはグループ関数(COUNT()
、MIN()
。..)を使用しない場合、HAVING
は WHERE
とマージされる。
サブ結合のそれぞれに、単純な
WHERE
が構造化され、サブ結合ごとに迅速に
WHERE
評価を取得し、可能な限り迅速にレコードをスキップする。
クエリ内の他のすべてのテーブルの前に、まず、すべての定数テーブルが読み込まれる。 定数テーブルとは以下のものを指す。
空白テーブルまたは 1 レコードのみのテーブル。
UNIQUE
インデックスまたは
PRIMARY KEY
を使う
WHERE
節とともに使用されるテーブルで、インデックス部分のすべてが定数式とともに使用され、そのインデックス部分が
NOT NULL
として定義されている場合。
以下のテーブルはすべて定数テーブルとして使用される。
mysql>SELECT * FROM t WHERE primary_key=1;
mysql>SELECT * FROM t1,t2
->WHERE t1.primary_key=1 AND t2.primary_key=t1.id;
テーブルを結合する最適な結合の組み合わせは、すべての可能性を試行してみることで発見される。ORDER
BY
および GROUP BY
内の全てのカラムが 1
つのテーブルに存在する場合、結合を行う時は第一にこのテーブルが選ばれる。
ORDER BY
節とそれと異なる
GROUP BY
節がある場合、あるいは、ORDER
BY
または GROUP BY
に結合キューの第 1
テーブルとは異なるテーブルのカラムが含まれている場合は、テンポラリテーブルが作成される。
SQL_SMALL_RESULT
を使用する場合、MySQL
ではメモリ内のテンポラリテーブルが使用される。
テーブルインデックスごとにクエリが行われ、スパンがレコードの 30% 未満である最適インデックスが使用される。このようなインデックスが検索されない場合は、クイックテーブルスキャンが使用される。
状況によっては、MySQL でデータファイルの参照もせずにインデックスからレコードを読み取れる場合もある。インデックスから使用されるカラムのすべてが数値型の場合、クエリの解決にはインデックスツリーのみが使用される。
レコードのそれぞれが出力される前に、HAVING
節と一致しないレコードはスキップされる。
非常に高速なクエリのサンプルをいくつか紹介します。
mysql>SELECT COUNT(*) FROM tbl_name;
mysql>SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;
mysql>SELECT MAX(key_part2) FROM tbl_name
->WHERE key_part_1=constant;
mysql>SELECT ... FROM tbl_name
->ORDER BY key_part1,key_part2,... LIMIT 10;
mysql>SELECT ... FROM tbl_name
->ORDER BY key_part1 DESC,key_part2 DESC,... LIMIT 10;
次のクエリは、インデックスツリーのみを使用して解決されます(インデックスのあるカラムが数値型であると想定)。
mysql>SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;
mysql>SELECT COUNT(*) FROM tbl_name
->WHERE key_part1=val1 AND key_part2=val2;
mysql>SELECT key_part2 FROM tbl_name GROUP BY key_part1;
The following queries use indexing to retrieve the rows in sorted order without a separate sorting pass: 次のクエリは、ソートのパスを分けることなく、ソートしたレコードを取り出すためにインデックスを使用します。
mysql>SELECT ... FROM tbl_name
->ORDER BY key_part1,key_part2,... ;
mysql>SELECT ... FROM tbl_name
->ORDER BY key_part1 DESC,key_part2 DESC,... ;
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.