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一起能够吧数据随机排序, ...
随机推荐
- 工具-VMWARE技巧-桥接连外网-WIN7
使用虚拟机wmware如何连接宿主主机 最简单的方法,使用直接连接主机的模式,然后把宿主机的IP更改为和虚拟机同一个网段的机器就行 但是既要上网,有要连接虚拟机,就需要使用桥接,在编辑->虚拟网 ...
- Apache + Tomcat 负载均衡 session复制
转自:http://blog.csdn.net/cssmhyl/article/details/8455400 http://snowolf.iteye.com/blog/743611 Apache ...
- Autodesk 举办的 Revit 2015 二次开发速成( 1.5 天),教室培训, 地点武汉
2014年8月26日9:00 – 17:00 2014年8月27日9:00 – 12:00 培训地点: Ø 湖北工业大学 实训楼605教室 Ø 地址:武汉市武昌区南湖李家墩一村一号 Ø 交通路线说明: ...
- UVA 294 - Divisors 因子个数
Mathematicians love all sorts of odd properties of numbers. For instance, they consider 945 to be an ...
- Gradle之依赖管理
Gradle之依赖管理 泡在网上的日子 / 文 发表于2015-01-29 16:12 第8824次阅读 Gradle,Android Studio 2 编辑推荐:稀土掘金,这是一个针对技术开发者的一 ...
- 杂项:CMM
ylbtech-杂项:CMM CMM是指“能力成熟度模型”,其英文全称为Capability Maturity Model for Software,英文缩写为SW-CMM,简称CMM.它是对于软件组 ...
- AJAX请求 $.ajaxSetup方法的使用
转自:https://blog.csdn.net/qq_23476319/article/details/78798885 jQuery.ajaxSetup()函数用于设置AJAX的全局默认设置. 该 ...
- BZOJ 3105 线性基 高斯消元
思路: 按照从大到小排个序 维护两个数组 一个是消元后的 另一个是 按照消元的位置排的 不断 维护从大到小 (呃具体见代码) //By SiriusRen #include <cstdio> ...
- 聊聊 TCP 中的 KeepAlive 机制
KeepAlive并不是TCP协议规范的一部分,但在几乎所有的TCP/IP协议栈(不管是Linux还是Windows)中,都实现了KeepAlive功能 RFC1122#TCP Keep-Alives ...
- 关于函数调用约定-thiscall调用约定
函数调用约定描述了如何以正确的方式调用某些特定类型的函数.包括了函数参数在栈上的分配顺序.有哪些参数将通过寄存器传入,以及在函数返回时函数栈的回收方式等. 函数调用约定的几种类型 stdcall,cd ...