您的位置:首页 > 数据库 > MySQL

mysql优化 之 group by索引松散扫描和紧凑扫描

2016-04-01 11:25 621 查看
group by语句利用B+tree索引扫描时分为松散扫描、紧凑扫描两种情况:
Loose Index Scan(松散扫描)就是只需要对索引扫描时取出很小一部分键值就能完成整个sql所需数据的扫描,在where条件含有范围谓词或者无条件、sql语句利用索引就能完成查询的才能使用上松散扫描,用上松散索引扫描的有如下几种类型的语句:

表t1有c1,c2,c3,c4四个字段,index为(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;
如上为官网给出能使用上松散索引扫描的情况,例如我这有个表有几百万的数据,建立了个拥有三个字段的索引。

mysql>select count(*) from history_20150425;
+--------------------+
| count(*)
+--------------------+
| 7880599
+--------------------+
共返回 1 行记录,花费 1734.54 ms.
mysql>alter table history_20150425 add index(dovalue,prevalue,taskid);
mysql> explain select dovalue,prevalue from history_20150425 group by dovalue,prevalue;
+----+-------------+----------------------------------+-------+---------------+--------------+---------+------+-------+------------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------------------------+-------+---------------+--------------+---------+------+-------+------------
| 1 | SIMPLE | history_20150425 | range | DoValue | DoValue | 8 | NULL | 65552 | Using index for group-by |
+----+-------------+----------------------------------+-------+---------------+--------------+---------+------+-------+------------
1 row in set (0.00 sec)

在extra列出现using index for group-by字样就表示利用上了loose index scan,其他情况就不贴出来了,有点浪费版面,可以自己按官网给出的类型自己试试。

Tight Index Scan(紧凑索引扫描),看完松散索引扫描就很好理解这个紧凑索引扫描了,就是需要读取所有数据才能满足查询所需数据。我们排除上面能用手松散扫描的情况就是紧凑扫描,下面依然是官方文档给出的例子:

例如表t1有c1,c2,c3,c4字段,index包含c1,c2,c3字段

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;
像这两个只能挨个扫描完索引片段才能得到准确的数据的语句,就不能使用松散索引扫描,

group by假如不能使用索引扫描完成,在使用临时表分组时内部会进行order by排序再分组,这里可以用order by null强制取消内部排序操作。

本文出自 “肖忠” 博客,请务必保留此出处http://xiaozhong991.blog.51cto.com/2354914/1759122
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: