余分なソートを行わずに ORDER
        BY の要求に応じるために、MySQL
        はインデックスを使用する場合があります。
      
        すべての使用されていないインデックス部分とほかの部分が
        WHERE
        節内で定数であるカラムである場合、ORDER
        BY
        がインデックスに完全にマッチしない場合でもこのインデックスを使用できます。次のクエリーではインデックスを使用して
        ORDER BY
        部分を解決します。
      
SELECT * FROM t1 ORDER BYkey_part1,key_part2,... ; SELECT * FROM t1 WHEREkey_part1=constantORDER BYkey_part2; SELECT * FROM t1 ORDER BYkey_part1DESC,key_part2DESC; SELECT * FROM t1 WHEREkey_part1=1 ORDER BYkey_part1DESC,key_part2DESC;
        MySQL で ORDER BY
        の解決にインデックスを使用できない場合
        (この場合も MySQL は
        WHERE
        節の条件に一致するレコードの検索にインデックスを使用します)。これには、次のような場合が含まれます。
      
            複数のキーに対して ORDER
            BY を実行する場合。
          
SELECT * FROM t1 ORDER BYkey1,key2;
            連続しないキー部分に対して
            ORDER BY
            を実行する場合。
          
SELECT * FROM t1 WHEREkey2=constantORDER BYkey_part2;
            ASC と
            DESC
            が混在している場合。
          
SELECT * FROM t1 ORDER BYkey_part1DESC,key_part2ASC;
            行の取り出しに使用されるキーが
            ORDER BY
            の実行に使用されるキーと異なる場合。
          
SELECT * FROM t1 WHEREkey2=constantORDER BYkey1;
            キーカラム名以外の項を含む式で
            ORDER BY
            を使用する場合。
          
SELECT * FROM t1 ORDER BY ABS(key); SELECT * FROM t1 ORDER BY -key;
            多数のテーブルを結合する場合で、行の取得に使用される最初の非定数テーブルのものでないカラムが
            ORDER BY
            に含まれているとき。(これは
            EXPLAIN
            で出力される最初の、const
            結合型でないテーブル。)
          
            ORDER BY と
            GROUP BY
            式が異なる場合。
          
            ORDER BY
            節に指定されたカラムの接頭辞だけにインデックスが設定されている場合。この場合、インデックスを使用してソート順序を完全に解決することはできません。たとえば、CHAR(20)
            のカラムがあり、その先頭の 10
            バイトだけにインデックスが設定されている場合、10
            バイト目よりあとの値はインデックスで区別できないため、filesort
            が必要になります。
          
            使用されたテーブルインデックスが、並び順にレコードを格納していないインデックスタイプの場合。(MEMORY
            テーブルの HASH
            インデックスなど。)
          
        インデックスをソートに使用できるかどうかは、カラムエイリアスの使用によって影響を受けることがあります。カラム
        t1.a
        にインデックスが設定されていると仮定します。次のステートメントで、選択リスト内のカラム名は
        a です。これは
        t1.a
        を指しているため、ORDER
        BY 内での a
        の参照にはインデックスを使用できます。
      
SELECT a FROM t1 ORDER BY a;
        次のステートメントでも、選択リスト内のカラム名は
        a
        ですが、これはエイリアスです。これは
        ABS(a)
        を指しているため、ORDER
        BY 内での a
        の参照にはインデックスを使用できません。
      
SELECT ABS(a) AS a FROM t1 ORDER BY a;
        次のステートメントでは、選択リスト内のカラム名とは異なる名前を
        ORDER BY
        で参照しています。ただし、t1
        には a
        というカラムがあるため、ORDER
        BY
        ではそれが使用され、インデックスは使用できます。(当然ながら、結果として
        ABS(a)
        の順序とはまったく異なるソート順序になります。)
      
SELECT ABS(a) AS b FROM t1 ORDER BY a;
        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;
        EXPLAIN SELECT ... ORDER BY
        を使用すると、MySQL
        でインデックスを使用してクエリーを解決できるかどうかを確認できます。Extra
        カラムに Using filesort
        が出力された場合は、MySQL で ORDER BY
        の解決にインデックスを使用できません。項4.2.1. 「EXPLAIN
        を使用して、クエリーを最適化する」
        を参照してください。
      
        MySQL には、結果をソートして取り出すための
        filesort
        アルゴリズムが 2 つあります。元のメソッドは
        ORDER BY
        のカラムだけを使用します。変更されたメソッドは、ORDER
        BY
        のカラムだけでなく、クエリーで使用されているすべてのカラムを使用します。
      
        どちらの filesort
        アルゴリズムを使用するかはオプティマイザが選択します。通常は変更されたアルゴリズムが使用されますが、BLOB
        カラムや TEXT
        カラムが対象となる場合には元のアルゴリズムが使用されます。
      
        元の filesort
        アルゴリズムは次のように動作します。
      
            キーに従って、あるいはテーブルスキャンによって、すべての行を読み取ります。WHERE
            節に一致しない行はスキップされます。
          
            各行について、1 組の値
            (ソートキーと行ポインタ)
            をバッファーに格納します。sort_buffer_size
            システム変数の値がバッファーのサイズになります。
          
バッファーが満杯になると、バッファーに qsort (クイックソート) を実行し、その結果を一時ファイルに格納します。ソートされたブロックのポインタを保存します。(すべての組がソートバッファーに収まる場合、一時ファイルは作成されません。)
すべての行が読み取られるまで、上記の手順を繰り返します。
            最大 MERGEBUFF (7)
            領域までのマルチマージを実行して 1
            つのブロックにし、別の一時ファイルに格納します。最初のファイルのすべてのブロックが
            2
            番目のファイルに格納されるまで、この処理を繰り返します。
          
            残りのブロック数が
            MERGEBUFF2 (15)
            未満になるまで、次の処理を繰り返します。
          
最後のマルチマージでは、行のポインタ (ソートキーの最後の部分) だけが結果ファイルに書き込まれます。
            結果ファイル内の行ポインタを使用して、ソートされた順序で行を読み取ります。これを最適化するには、行ポインタを大きなブロックで読み込んでソートし、ソートした行ポインタを使用して、ソートされた順序で行を行バッファーに読み込みます。sort_buffer_size
            システム変数の値がバッファーのサイズになります。この手順のコードは
            sql/records.cc
            ソースファイルにあります。
          
        このアプローチの問題の 1 つは、行を
        WHERE 節の評価時に 1
        回、値の組をソートしたあとにもう 1 回、合計
        2 回読み取ることです。また、1
        回目は行に連続してアクセスできても
        (テーブルスキャンを実行する場合など)、2
        回目のアクセスはランダムになります。(ソートキーは順に並べ替えられますが、行の位置は変更されないため。)
      
        変更された filesort
        アルゴリズムは、ソートキーの値と行の位置だけでなく、クエリーに必要なカラムも記録するように最適化されています。これにより行の
        2 度読みを避けられます。変更された
        filesort
        アルゴリズムは次のように動作します。
      
            WHERE
            節とマッチする行を読む。
          
各行ごとに、クエリーに必要なカラムとソートキー値と行ポジションを含むタプル値を記憶する。
ソートキー値でタプルを並べ替える
並べ替えられた順序で行を取得しますが、テーブルに 2 度アクセスするよりも、並べ替えられたタプルから必要なカラムを読み取ります。
        変更された filesort
        アルゴリズムを使用すると、元のアルゴリズムで使用される組よりもタプルが長くなり、ソートバッファーに収まるタプル数は少なくなります
        (ソートバッファーのサイズは
        sort_buffer_size
        で指定される)。その結果、追加の I/O
        が発生して、変更されたアルゴリズムの速度は逆に低下する可能性があります。速度低下を避けるため、この最適化は、ソートタプル内の追加カラムの合計サイズが
        max_length_for_sort_data
        システム変数の値を超えない場合にかぎり使用されます。(この変数が高く設定されると、活発なディスクアク活動に対して低い
        CPU 活動といった状態が発生します)。
      
        filesort
        が使用されていない低速のクエリーでは、filesort
        が発生するように
        max_length_for_sort_data
        を小さくしてみることもできます。
      
        ORDER BY
        速度を上げたい場合、MySQL
        が余分な並べ替えフレーズよりもインデックスを使用できるか確認してください。これが不可能な場合、次の手段を試してみてください。
      
            sort_buffer_size
            変数のサイズを大きくしてください。
          
            read_rnd_buffer_size
            変数のサイズを大きくしてください。
          
            値を保持するために必要な最小限のサイズでカラムを宣言することにより、行あたりに使用する
            RAM を減らしてください。たとえば、値が 16
            文字を超えることがない場合は、CHAR(16)
            の方が CHAR(200)
            よりも適切です。
          
            tmpdir
            を変更して、空き領域が多い専用のファイルシステムを指定してください。また、このオプションはラウンドロビン方式で複数のパスを受け入れるため、この機能を使用して複数のディレクトリに負荷を分散できます。パスは、Unix
            ではコロン
            (「:」)
            で区切り、Windows、NetWare、および OS/2
            ではセミコロン
            (「;」)
            で区切るようにしてください。パスは、同じディスク上の異なるパーティションではなく、異なる
            物理
            ディスク上にあるファイルシステム内のディレクトリを指すようにします。
          

