クエリの抽出結果を並び替える
mysql> SELECT * FROM article ORDER BY created_at DESC LIMIT 10;
この場合は、created_にインデックスを貼ることでソート処理を排除することができます。というのも、
さらに、
このようにソート処理はインデックスを貼ることが一番の解決策ですが、
今回はソート最適化や動作について紹介したいと思います。
ソート処理の動作
MySQLは最初にORDER BY句の条件がインデックスで解決できるか確認します。インデックスでソートが解決されたかどうかはEXPLAINから確認することができます。Extra列にUsing filesortの記述がなければ、
このソート処理は2種類あり、sort_システム変数で指定された値のバッファ
- 従来の方式
- テーブルから行を読み取り、
ソートバッファのタプルとしてソートキーとrow IDを詰め、 クイックソート処理を行います。バッファがいっぱいになった場合はテンポラリファイルに書き出します。テンポラリファイルとはマージソート処理を行い、 ソートバッファをマージします。ソートが完了すると、 ソートされた順序を維持しながらrow IDから対象の行を読み取ります。よって、 ソート処理のための行読み取りと、 ソート後の対象行読み取りの2回の行読み取りが発生します。 - 新しい方式
- これはrow IDではなく、
SELECTで指定されたカラムタプルをソートバッファに詰めます。ソートが完了までは従来の方式と同じです。ソートが完了すると、 ソートされた順序で読み出します。従来の方式とは違い、 直接必要なカラムを取得できるので、 ソート処理のための行読み取りの1回の行読み取りで完了します。
選択方法
どちらの方式をオプティマイザーが選択するかはmax_システム変数の値により変わります。ソートバッファに詰めるソートキーおよびSELECTで指定されたカラムタプルの行の合計サイズがこの変数より小さい場合は、
- ※)
- しかし、
注意として max_についてのドキュメントを見てみると、length_ for_ sort_ data これからリリースされるMySQL8. 0.20からDeprecatedになるようです (2019/ 11/ 25現在)。
MySQL 8.max_システム変数は無視され、
確認方法
どちらの方式選択されたか確認するには、"sort_というキーの値を確認します。"<sort_は従来の方式です。"<sort_は新しい方式です。
また、"<sort_と表示されることもあります。これも新しい方式で、
新しい方式が選択されると、
"filesort_summary": {
"rows": 16777217,
"examined_rows": 16777217,
"number_of_tmp_files": 11268,
"sort_buffer_size": 32760,
"sort_mode": "<sort_key, rowid>"
ちなみに、Sort_ステータス変数または、"number_キーの値から確認できます。
"filesort_summary": {
"rows": 16777217,
"examined_rows": 16777217,
"number_of_tmp_files": 16385,
"sort_buffer_size": 32768,
"sort_mode": "<sort_key, additional_fields>"
}
LIMIT句の最適化
MySQL 5.
この最適化はLIMIT句で指定された件数分のカラムタプルがソートバッファに収まるかを実行前に計算します。収まる場合は、
最適化されたかどうかはoptimizer_"filesort_キーを確認します。"chosen"キーの値がtrueであれば最適化されています。
"filesort_priority_queue_optimization": {
"limit": 10,
"rows_estimate": 263778088,
"row_size": 14,
"memory_available": 32768,
"chosen": true
},
"filesort_priority_queue_optimization": {
"limit": 10000,
"rows_estimate": 263778088,
"row_size": 24,
"memory_available": 32768,
"strip_additional_fields": {
"row_size": 22,
"chosen": false,
"cause": "not_enough_space"
}
"chosen"キーの値がfalseとなり、"cause"キーに最適化できなかった理由が確認できます。
まとめ
最適化された処理など紹介しましたが、
今回紹介した内容は以下のドキュメントから確認できます。