GROUP BY
を処理するもっとも効率的な方法は、インデックスを使用してグループ分けカラムを直接取得することです。このアクセスメソッドで、MySQL
はキーが順序づけられている、インデックス型の特性を利用します。(たとえば、BTREE
)。この特性はすべての
WHERE
条件を満たすインデックス内のキーを考慮せずとも、インデックス内のルックアップグループの使用を可能にします。このアクセスメソッドはインデックス内のほんの一部のキーを考慮するため、loose
index
scanと呼ばれています。WHERE
節がない場合、ルースインデックススキャン
(loose index scan)
はナンバーグループの数だけキーを読みます。これはキーの総数よりも少ない数かもしれません。もし
WHERE
節がレンジ前提を含む場合、(項4.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;