数据库优化七SQL优化之SELECT优化——groupby优化在数据库查询中,group by语句经常使⽤,⽽这个语句的使⽤是最耗性能的,按常理,
我们⽣活中要这样做也很⿇烦,有两种情形:
1、有索引的情况
2、⽆索引的情况
sql语句优化方式对于第⼀种情况,如果在⽣活中要做这样的事情,很恼⽕,我们正常的想法是,先把所有的
按⾼矮顺序来排序,最后是⼀组的就直接挑出来了,但怎样实现这个排序呢?
根据上⼀篇⽂件排序filesort的规则,我们可以这样,先让局部有序,然后在慢慢扩散
来排列整个数据,⽅法是:选择适当的⼤⼩的排序块缓存⼤⼩,每次取出块⼤⼩数据,利⽤
快速排序功能对该块排序,然后存⼊临时⽂件,然后利⽤归并排序的思想,将各个块之间进⾏
排序,最终达到排序完成。
对于上⾯的描述,虽然排序使⽤了⾮常快的排序算法快排和归并排序,但这个涉及的临时
⽂件的读取操作,浪费⼤量的I/O,性能上是危害很⼤的,因此,掌握好在使⽤group by的语句的
使⽤,尽量使⽤到索引,免除了排序的操作,group by的速度就上来了,并且也不会消耗太多
内存⼤⼩,下⾯叙述⼀下group by使⽤索引的原理
⼀、 group by 使⽤索引原理
1、group by 使⽤排序来读取数据,所以只能⽤btree索引,不能使⽤在hash索引的算法中
因为hash索引是⼀种类似键值对的快速访问⽅式,这个对于指定某个值查询很好,但
没有排序的⽅法,其使⽤的hash函数 + 碰撞冲突解决⽅案
2、当使⽤索引排序来查数据时,不会在explain中extra列看到有using filesort
3、在group by操作完成后,还会对group出来的结果进⾏排序,因此如果对排序的结果
没有排序的需求,可以考虑在其后⾯加上order by null
⼆、group by 访问索引的⽅法
group by 访问数据有两种⽅法:
1、边扫描边执⾏group操作,叫做松散索引扫描(Loose index scan)
2、先执⾏⼀个范围(range)扫描,然后在执⾏group 操作,叫做
紧索引扫描(Tight index scan)
2.1、松散索引扫描(Loose index scan)
最⾼效的处理group by的⽅法是,直接访问相应的索引,所以不⽤排序就能根据
索引来读取需要的数据,⽽对于如聚簇索引(cluster index),我们可以读取前⾯的⼀部分
的字段索引来获取数据,⽽不⽤满⾜所有的列,这就叫做松散索引扫描,我的定义可为:
前缀索引扫描
使⽤松散索引扫描的条件:
1、查询只能针对⼀个单表进⾏操作,这个可是个致命的缺点啊,但如果where
条件⽐较多,选出来的数据少的话,还是不⽤担忧的
2、group by使⽤索引为:对聚簇索引使⽤前缀索引
3、使⽤类似group by 的操作的函数有distinct函数,使⽤此函数时,要么在⼀个
索引上使⽤,要么在group by时,其group by的字句是索引扫描,否则会引
起全表扫描。
4、在使⽤group by语句中,如果使⽤聚合函数max(), min()等,如果列不在group
by的列中,或不在group by 列的聚簇索引的⼀部分,这将会⽤到排序操作
5、只能对整个列的值排序时使⽤到索引,⽽只有前⾯⼀部分索引不能⽤到排序,
如:列 c1 char(20), index(c1(10))、这个只⽤了⼀半索引,将⽆法使⽤来对
整个数据排序
假设我们在表t1(c1, c2, c3, c4)有聚簇索引index(c1, c2, c3),能使⽤Loose index scan例⼦:[sql]
1. 1、SELECT c1, c2 FROM t1 GROUP BY c1, c2;
2. 2、SELECT DISTINCT c1, c2 FROM t1;
3. 3、SELECT c1, MIN(c2) FROM t1 GROUP BY c1;
4. 4、SELECT c1, c2 FROM t1 WHERE c1 < const GROUP BY c1, c2;
5. 5、SELECT MAX(c3), MIN(c3), c1, c2 FROM t1 WHERE c2 > const GROUP BY c1, c2;
6. 6、SELECT c2 FROM t1 WHERE c1 < const GROUP BY c1, c2;
7. 7、SELECT c1, c2 FROM t1 WHERE c3 = const GROUP BY c1, c2;
原因解释:
这些都使⽤了前缀索引
2.2、使⽤紧索引扫描和松索引扫描类似,只是会先根据where条件来获取所有的⾏,然后
根据group by的字段来分组,这种的使⽤⽅法,⼀般是,where条件返回的⾏较少时
使⽤,⽐如,你的where字句中使⽤了主键或唯⼀键=const等,这样的代价是,通过
where过滤出来的⾏很少,再分组操作时也很快的
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论