GROUP BY算法: 有3种,
a). 使用临时表。创建临时表,放入要group by的数据,按照group by的字段进行排序,生成group by结果集以及计算聚合函数的结果
b). Loose Index Scan
使用条件是针对单表的查询;group by的字段按照顺序前导匹配某个索引;索引必须是有序的;聚合函数只包含min、max,字段必须相同并且在索引中,并且是索引中紧跟着group by字段的下一个字段;索引字段中除了group by的字段外,其他字段如果出现在where条件中,where条件只能是常量值。MySQL 5.4.4加入了几个新的聚合函数:AVG(DISTINCT), SUM(DISTINCT), 和COUNT(DISTINCT),也是有限制性的
这种方式只需要部分扫描索引即可完成group by操作,如果where子句中只有group by字段的条件,则索引扫描的层级只需要到group by包含的字段(如果索引除了group by字段之外还包含其他字段,这种处理方式根本不需要扫描到索引页节点等层级)。正因为索引中包含的信息有限,因此该算法对聚合函数、索引的要求非常多,适用的场景比较窄,但是效率是最高的
例如表t1(c1,c2,c3,c4),有索引idx(c1,c2,c3),下面语句可以使用Loose Index Scan:
SELECT c1, c2 FROM t1 GROUP BY c1, c2;
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;
c). Tight Index Scan
其实就是利用有序索引的特性,避免创建临时表以及额外的排序操作,因此前提条件是能够利用有序索引;仅通过索引扫描可以完成查询
例如表t1(c1,c2,c3,c4),有索引idx(c1,c2,c3),下面2个语句都可以使用Tight Index Scan进行group by:
SELECT c1, c2, c3 FROM t1 WHERE c2 = 'a' GROUP BY c1, c3;
SELECT c1, c2, c3 FROM t1 WHERE c1 = 'a' GROUP BY c2, c3;
在EXPLAIN中,Extra中出现Using index for group-by表示使用Loose Index Scan实现;Using Temporary表示使用临时表实现;否则表示使用Tight Index Scan实现