余分なソートを行わずに ORDER
BY
の要求に応じるために、MySQL
はインデックスを使用する場合があります。
全ての使用されていないインデックス部分と他の部分が
WHERE
節内で定数であるカラムである場合、ORDER
BY
がインデックスに完全にマッチしない場合でもこのインデックスを使用できます。次のクエリではインデックスを使用して
ORDER BY
部分を解決します。
SELECT * FROM t1 ORDER BYkey_part1
,key_part2
,... ; SELECT * FROM t1 WHEREkey_part1
=constant
ORDER BYkey_part2
; SELECT * FROM t1 ORDER BYkey_part1
DESC,key_part2
DESC; SELECT * FROM t1 WHEREkey_part1
=1 ORDER BYkey_part1
DESC,key_part2
DESC;
MySQL で ORDER
BY
の解決にインデックスを使用できない場合は以下のとおりです(この場合も
MySQL は
WHERE
節の条件に一致するレコードの検索にインデックスを使用します)。
複数のキーに対してORDER
BY
を実行する場合。
SELECT * FROM t1 ORDER BYkey1
,key2
;
連続しないキー部分に対してORDER
BY
を実行する場合。
SELECT * FROM t1 WHEREkey2
=constant
ORDER BYkey_part2
;
ASC
とDESC
が混在している場合。
SELECT * FROM t1 ORDER BYkey_part1
DESC,key_part2
ASC;
行の取り出しに使用されるキーが ORDER
BY
の実行に使用されるキーと異なる場合。
SELECT * FROM t1 WHEREkey2
=constant
ORDER BYkey1
;
ORDER
BY
で多くのテーブルとカラムを結合していて、それら全てがレコードの取り出しに使用される最初の非
const テーブルではない場合(これは
EXPLAIN
で出力される最初のテーブルで、かつ、const
メソッドを使用していないテーブル)。
ORDER BY
とGROUP
BY
式が異なる場合。
使用されたテーブルインデックスが、並び順にレコードを格納していないインデックスタイプの場合。(MEMORY
テーブルの
HASH
インデックスなど)。
EXPLAIN SELECT ... ORDER
BY
を使用すると、MySQL
でインデックスを使用してクエリを解決できるかどうかをチェックできます。Extra
カラムに
Using
filesort
が出力された場合は、MySQL で ORDER
BY の解決にインデックスを使用できません。
項6.2.1. 「EXPLAIN
を使用して、クエリを最適化する」を参照してください。
ソートキー値と行ポジションだけでなく、クエリに必要なカラムまで記憶するfilesort
最適化が使用されます。これにより行の2度読みを避けられます。filesort
アルゴリズムは以下のように実行されます。
WHERE
節とマッチする行を読む。
各行ごとに、クエリに必要なカラムとソートキー値と行ポジションを含むタプル値を記憶する。
ソートキー値でタプルを並べ替える
並べ替えられた順序で行を取得しますが、テーブルに2度アクセスするよりも、並べ替えられたタプルから必要なカラムを読み取ります。
MySQLの旧バージョンで使用されていたアルゴリズムよりも格段に改良されています。
遅滞を避けるため、この最適化はmax_length_for_sort_data
システム変数の値をソートタプル内の余分なカラムのトータルサイズが超えない場合使用されます。(この変数が高く設定されると、活発なディスクアク活動に対して低いCPU活動といった状態が発生します。)
ORDER
BY
速度を上げたい場合、MySQLが余分な並び替えフレーズよりもインデックスを使用できるか確認してください。これが不可能な場合、以下の手段を試してみてください。
sort_buffer_size
変数のサイズを大きくしてください。
read_rnd_buffer_size
変数のサイズを大きくしてください。
tmpdir
を変更することで、秋スペースの要領が多い専用のファイルシステムを示してください。この選択肢はラウンドロビン方式で複数のパスを受領します。Unixでは、パスはコロンを含む文字(‘:
’)
で分けられ、ウィンドウズ、Netware, そして
OS/2
ではセミコロンを含む文字(‘;
’)で分けられるべきです。
この特性を利用して複数のディレクトリに渡り負荷を分散することができます。注:パスは、同ディスクのパーティションで分けられた領域ではなく、異なる物理的なディスクのファイルシステム内のディレクトリに通じます。
MySQLはデフォルトで、GROUP BY
の全クエリをcol1
、col2
,
...ORDER BY
で指定したかのように、クエリをソートします。同じカラムリストを含むcol1
、col2
,
...ORDER
BY
節を明示的に取り入れた場合、ソートが実行されるとはいえ、MySQLは速度ペナルティなしに最適化します。クエリにGROUP
BY
が含まれていながら、結果のソートに費やすオーバーヘッドを避けたい場合、ORDER
BY
NULL
を指定することでソートを実行しないようにすることができます。例
:
INSERT INTO foo SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL;