GROUP
BY
を処理する最も効率的な方法は、グループフィールドを直接取得するのにインデックスが使用されるときです。このアクセスメソッドで、MySQLはキーが順序づけられている、インデックス型の特性を利用します。(例えば、BTREE
)。この特性は全てのWHERE
条件を満たすインデックス内のキーを考慮せずとも、インデックス内のルックアップグループの仕様を可能にします。.このアクセスメソッドはインデックス内のほんの一部のキーを考慮するため、loose
index
scanと呼ばれています。WHERE
節がない場合、ルースインデックススキャン(loose
index
scan)はナンバーグループの数だけキーを読みます。これはキーの総数よりも少ない数かもしれません。もしWHERE
節がレンジ前提を含む場合、(項6.2.1. 「EXPLAIN
を使用して、クエリを最適化する」内に記述されたrange
join型に関するディスカッションを参照してください),
a loose index scan
はレンジ条件を満たす各グループの最初のキーを参照し、最低限のキーの数を読みます。これは以下の条件下で可能になります。
クエリはシングルテーブル上にある。
GROUP
BY
はインデックスの最初の連続部分を含む。(もし、GROUP
BY
の代わりにクエリがDISTINCT
節を含む場合、全ての異なる属性はインデックスの最初を参照する。)
使用される集約ファンクション(ある場合)はMIN()
とMAX()
であり、全て同じカラムを参照します。
クエリで参照されたGROUP
BY
以外のインデックス部分は定数でなければいけません(つまり、定数と等価であるよう参照されなければいけません)が、MIN()
あるいはMAX()
ファンクションは例外です。
そのようなクエリのEXPLAIN
出力はExtra
カラム内のUsing index for
group-by
を示します。
テーブルt1(c1,c2,c3,c4)
にインデックスidx(c1,c2,c3)
があることを前提に、以下のクエリがこのカテゴリに属します。
SELECT c1, c2 FROM t1 GROUP BY c1, c2; SELECT DISTINCT c1, c2 FROM t1; SELECT c1, MIN(c2) FROM t1 GROUP BY c1; SELECT c1, c2 FROM t1 WHERE c1 <const
GROUP BY c1, c2; SELECT MAX(c3), MIN(c3), c1, c2 FROM t1 WHERE c2 >const
GROUP BY c1, c2; SELECT c2 FROM t1 WHERE c1 <const
GROUP BY c1, c2; SELECT c1, c2 FROM t1 WHERE c3 =const
GROUP BY c1, c2;
以下の理由により以下のクエリはこのクイックセレクトメソッドを使用しての実行はできません。
MIN()
やMAX()
以外の集約ファンクションが存在します。例えば:
SELECT c1, SUM(c2) FROM t1 GROUP BY c1;
以下で示されるよう、GROUP
BY
節内のフィールドはインデックスの最初の部分に属するものではありません。
SELECT c1,c2 FROM t1 GROUP BY c2, c3;
クエリは、定数と等価ではない、GROUP
BY
部分の後にくるキー部分を参照しています。
SELECT c1,c3 FROM t1 GROUP BY c1, c2;