mysql5.7官网直译SQL语句优化--分组优化
1.14Group By Optimization 分组优化
大多数方法为了满足分组查询需要扫描整个表并且创建一个临时表,其中每组中的值都是连续的,如果可以使用聚合函数和临时表获取各个分组。在某些情况下,mysql能够通过使用索引方法从而避免创建临时表来提高查询效率。
在group by中使用索引的前提条件是group by中的列都是来自相同的索引,并且索引中存储的是有序的key(例如,是一个BTREE索引,而不是HASH索引)。是否能用索引方法代替临时表的依据是哪一部分的索引被用在查询中,这一部分的条件是特殊的和聚合函数。
有两种方法在group by查询中使用索引方法,在接下来的部分详细描述。第一种方法,分组操作是用于任意范围谓词的使用。第二种方法是首先完成一个范围查询,然后对结果数据进行分组。
在mysql,GROUP BY被用于排序,所以服务器会使用order by优化器来分组。然而,并不赞成依赖GROUP BY的排序。请看8.2.1.13的order by优化
>松散索引扫描
最有效的处理分组的方法是在分组的列上直接使用索引。通过这种方法,mysql使用索引类型的特有属性如有序性(例如BTREE索引)。该特性使得查找分组在一个索引值上而不需要考虑所有满足where条件的全部索引的值。这种方法只会考虑索引的一小部分值,所以也被称为松散索引扫描。当没有一个where条件时,一个松散索引扫描读取的索引数量和分组数量相同,但依然要比全部索引值要少很多。如果where条件包含了范围查找,松散索引扫描每一组中满足范围条件的第一个key,并且再读取最少的可能数量的索引。这个可能性的条件如下:
1)查询覆盖了一张简单的表
2)group by中的列形式必须是满足索引左前缀,而不能再有其他列。(如果,除了group by,查询中有不同的条件,所有不同的属性引用列的形式是一个左前缀索引)例如,如果表t1中有一个索引在(c1,c2,c3),松散索引扫描可以使用,当查询有group by c1,c2。如果查询是group by c2,c3,或者是group by c1,c2,c4,则松散索引不可用。
3) 在查询的列展示中使用的聚合函数只有MIN()和MAX(),所有他们引用的都是相同的列。该列必须是一个索引并且必须直接跟在group by的后面。
4)除了group by引用的这些,剩下的索引中的其他部分必须都是常量(也就是说,他们必须引用的是常数类型),除了讨论MIN()或者是MAX()函数。
5)对于索引列,全部值必须都是被索引的,并不仅仅是一个前缀,例如,c1 VARCHAR(20),INDEX(c1(10)),索引不能被用于松散索引。
如果一个查询中使用了松散索引查询,EXPLAIN输出中会展示Using index for group-by在Extra列中。
假设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;
下面的查询不能使用这种快速查询的方法,理由如下:
1)使用了除MIN()和MAX()之外的聚合函数:
SELECT c1, SUM(c2) FROM t1 GROUP BY c1;
2) 在group by中的列不是最左前缀索引形式的:
SELECT c1, c2 FROM t1 GROUP BY c2, c3;
3)查询引用的索引的部分和在group by之后的部分对于一个常量来说并不是等价的:
SELECT c1, c3 FROM t1 GROUP BY c1, c2;
如果查询中使用了where c3=const ,则松散索引扫描能够使用。
松散索引扫描方法能够使用在其他形式的聚合函数引用中出现在查询列表中,除了已经支持的MIN()和MAX()函数的引用:
1)AVG(DISTINCT),SUM(DISTINCT),和COUNT(DISTINCT)也被支持。AVG(DISTINCT)和SUM(DISTINCT)使用单一参数。COUNT(DISTINCT)能够有多余一个列的参数。
2)必须没有group by或者是DISTINCT条件在查询中。
3)先前对松散扫描限制的描述任然适用。
假设在表t1(c1,c2,c3,c4)中有一索引idx(c1,c2,c3),那么松散索引扫描方法能够用于如下的查询:
SELECT COUNT(DISTINCT c1), SUM(DISTINCT c1) FROM t1;
SELECT COUNT(DISTINCT c1, c2), COUNT(DISTINCT c2, c1) FROM t1;
>紧凑索引扫描
紧凑的索引扫描也许是一个全表索引扫描,也许是一个范围的索引扫描,完全由查询条件决定:
当对松散索引的查询条件不满足时,对于group by查询依然尽可能避免创建临时表。如果有一个范围查询在where条件中,该方法将只会读取满足where条件的全部key集合。否则,它将会是一个全索引的扫描。因为该方法会读取满足where条件的所有索引的值或者是对于没有范围条件的全部索引的值,我们定义它为一个紧凑的索引扫描。通过一个紧凑的索引扫描,分组操作通过读取满足条件的全部索引值来完成。
为了使用紧凑索引扫描方法,充分条件是存在一个恒定等价的条件对于查询中引用的全部列都来自group by中的key或者部分来自其中。恒等条件能填充任何对于查询keys的空白,所以可以是前缀索引。前缀索引能够被用于索引查找。如果我们要求对group by的结果排序,且形成查询key是前缀索引形式的是可能的,mysql也避免了额外的排序操作因为查询有序的前缀索引已经对所有的key排好序了。
假设有一个索引idx(c1,c2,c3)在t1(c1,c2,c3,c4)。下面的查询不能用之前描述的松散索引查询方法,但依然能够用紧凑索引查询方法。
1)group by中有一个空白,但是被条件c2='a'覆盖了。
SELECT c1, c2, c3 FROM t1 WHERE c2 = 'a' GROUP BY c1, c3;
2)group by不是以索引的第一部分开始的,但是查询条件中听了该部分的常量条件:
SELECT c1, c2, c3 FROM t1 WHERE c1 = 'a' GROUP BY c2, c3;
到此关于group by的优化就结束了,之后我们将介绍的是1.15的DISTINC Optimization
mysql5.7官网直译SQL语句优化--分组优化的更多相关文章
- mysql5.7官网直译SQL语句优化--select语句优化
8.2 sql语句优化 大致内容如下: 8.2.1:SELECT语句的优化 8.2.2:优化子查询,派生表和试图引用 8.2.3:优化INFORMATION_SCHEMA查询 8.2.4:优化数据改变 ...
- 《MySQL慢查询优化》之SQL语句及索引优化
1.慢查询优化方式 服务器硬件升级优化 Mysql服务器软件优化 数据库表结构优化 SQL语句及索引优化 本文重点关注于SQL语句及索引优化,关于其他优化方式以及索引原理等,请关注本人<MySQ ...
- Oracle SQL语句之常见优化方法总结--不定更新
1.SQL语句尽量用大写的: 因为oracle总是先解析SQL语句,把小写的字母转换成大写的再执行. 2.WHERE子句中的连接顺序: ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理, ...
- SQl语句查询性能优化
[摘要]本文从DBMS的查询优化器对SQL查询语句进行性能优化的角度出发,结合数据库理论,从查询表达式及其多种查询条件组合对数据库查询性能优化进行分析,总结出多种提高数据库查询性能优化策略,介绍索引的 ...
- MySQL中一个sql语句包含in优化问题
第一版sql: SELECT module.id, module.module_name, module.module_code `module` where IN (module.did_acces ...
- 3,SQL语句及数据库优化
1,统一SQL语句的写法 对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的. 所以封装成复用方法,用标准模板来控制. select*from dual select*Fr ...
- Oracle SQL语句之常见优化方法总结
1.用EXISTS替换DISTINCT 当SQL包含一对多表查询时,避免在SELECT子句中使用DISTINCT,一般用EXIST替换,EXISTS(低效): SELECT DISTINCT USER ...
- SQL语句及数据库优化
1,统一SQL语句的写法 对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的. 所以封装成复用方法,用标准模板来控制. select*from dual select*Fro ...
- Mysql sql语句技巧与优化
一.常见sql技巧 1.正则表达式的使用 2.巧用RAND()提取随机行 mysql数据库中有一个随机函数rand()是获取一个0-1之间的数,利用这个函数和order by一起能够吧数据随机排序, ...
随机推荐
- Google Spanner (中文版)
温馨提示:本论文由厦门大学计算机系林子雨翻译自英文论文,转载请注明出处,仅用于学习交流,请勿用于商业用途. [本文翻译的原始出处:厦门大学计算机系数据库实验室网站林子雨老师的云数据库技术资料专区htt ...
- POJ 2191
只会打表 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring ...
- MQTT---HiveMQ源代码具体解释(八)Netty-WebSocket
源博客地址:http://blog.csdn.net/pipinet123 MQTT交流群:221405150 基于netty实现Webscoket相对来说就是相当简单,所以本讲中就不搞太复杂的了,给 ...
- “XXX.Index”不扩展类“System.Web.UI.Page”,因此此处不同意的问题
"XXX.Index"不扩展类"System.Web.UI.Page",因此此处不同意的问题 原因:设计页面继承的路径和后台.cs页面类的路径不一致造成的 看下 ...
- Java集合(二):List列表
在上一节中,介绍了Java集合的总体情况.从这节開始,将介绍详细的类.这里不单单介绍类的使用方法.还会试图从源代码的角度分析类的实现.这一节将介绍List接口及实现类.即列表中的链表LinkedLis ...
- hdoj--2579--Dating with girls(2)(搜索+三维标记)
Dating with girls(2) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- ubuntu16.04+caffe训练mnist数据集
1. caffe-master文件夹权限修改 下载的caffe源码编译的caffe-master文件夹貌似没有写入权限,输入以下命令修改: sudo chmod -R 777 ~/caffe-ma ...
- Java-API-POI:POI百科
ylbtech-Java-API:POI百科 Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 1. ...
- 17.QT键盘
mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> 5 #include <Q ...
- OC中的类扩展
类扩展 是在原有类的基础扩展一个新的属性和对象方法 但是方法的实现还是要写在原有的声明中,不然是不会被访问到的 类扩展可以扩展在新的头文件中,然后在主函数中导入. 利用类扩展可以变相的实现属性的私有化 ...