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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql优化 之 group by索引松散扫描和紧凑扫描相关的知识,希望对你有一定的参考价值。

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

以上是关于mysql优化 之 group by索引松散扫描和紧凑扫描的主要内容,如果未能解决你的问题,请参考以下文章

利用 group by 的 Loose Index Scan 优化 sql

MYSQL优化-之GROUP BY

MySQL优化:order by和limit

group by 的优化

一次 group by + order by 性能优化分析

MYSQL性能调优05_覆盖索引索引下推如何选择合适的索引Order by与Group by优化索引设计原则