MYSQL GROUP BY Optimization
GROUP BY Optimization
常规的匹配group by(分组)操作子句是扫整表并且创建包含连续的分组行的临时表, 利用临时表得到group数据,运用appregate functions(聚合函数)(有的话)。有些情况下,MYSQL 可能更好的通过使用Index access来避免临时表的创建。
利用indexes access避免临时表最重要的先决条件是:所有的group by子句中的列属性必须来至同一个index(联合),并且index的存储以它的关键字顺序(BTree index,hash index不是顺序的).是否用index access而不是creation of temporary table也依赖查询语句引用的index部分属性,指定的条件部分(where),和select子句中的聚合函数。
Loose Index Scan(松散索引扫描)
最有效率处理group by方法是当直接使用index获得检索分组列属性。此时MYSQL会利用index关键字有序的属性(BTREE),该属性确保在一个index中查找组信息而不用考虑该index中所有的关键字(是否满足where子句条件)。该access 方法只考虑一个index中一部分关键字,所以它被成为loose index scan.当查询语句中没有where子句时,loose index scan读取
需要的key,比读全部key要小。如果where子句包含范围条件,loose index scan查找每个组中第一个key满足range条件,再次读取尽可能少的key数量,需要满足以下几点:
假设在table t1(c1,c2,c3,c4)上存在一个index idx(c1,c2,c3), loose index scan方法在一下几种情况下会被使用:
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;
一下 查询不会使用loose index scan:
1:select中出现的except group by 列的index列关键字,只能以 = 或 min(),max()出现;
SELECT c1, SUM(c2) FROM t1 GROUP BY c1;
2:最左前缀
SELECT c1, c2 FROM t1 GROUP BY c2, c3;
3:同1解释
SELECT c1, c3 FROM t1 GROUP BY c1, c2;
松散索引扫描也可以使用在其他形式的聚合函数: AVG(DISTINCT),SUM(DISTINCT)(单列),COUNT(DISTINCT)(多列)支持。条件:
1: 没有group by或者 distinct子句在查询中
2: 前面提到的限制依然适用
适用:
SELECT COUNT(DISTINCT c1), SUM(DISTINCT c1) FROM t1; SELECT COUNT(DISTINCT c1, c2), COUNT(DISTINCT c2, c1) FROM t1;
不适用:
SELECT DISTINCT COUNT(DISTINCT c1) FROM t1; SELECT COUNT(DISTINCT c1) FROM t1 GROUP BY c1;
Tight Index Scan(紧凑索引扫描)
紧凑索引扫描要不是全索引扫描要不是区间索引扫描。
当松散索引扫描不能使用的时候,依然可以避免创建临时表。如果where子句中有range条件,那么只读取满足条件的key。
否则执行全索引扫描。因为算法读取所有满足range条件的key,或者如果没有条件扫描整个索引,我们称为紧凑索引扫描。
使用紧凑索引扫描,分组操作只有在所有key找完之后执行。
算法在使用等式比较所有查询引用的列生效,只有等式常量能够填上查询key的间隙,才有可能形成索引的前缀,使用索引前缀来进行索引查找。
这样mysql可以避免额外的排序操作直接可以从索引中顺序获取。假设index(c1,c2,c3)在表table(c1,c2,c3,c4),下面的查询不支持松散索引扫描,但是支持紧凑索引扫描
1:虽然有空隙但是已经被where c2=’a’填补
SELECT c1, c2, c3 FROM t1 WHERE c2 = 'a' GROUP BY c1, c3;
2: 虽然group by不是和索引第一位匹配,但是where中提供了和常量的比较
SELECT c1, c2, c3 FROM t1 WHERE c1 = 'a' GROUP BY c2, c3;
mysql> desc select distinct first_name from employees ;
+----+-------------+-----------+-------+---------------+-----------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+-----------+---------+------+------+--------------------------+
| 1 | SIMPLE | employees | range | idx_fn_ln | idx_fn_ln | 16 | NULL | 2495 | Using index for group-by |
+----+-------------+-----------+-------+---------------+-----------+---------+------+------+--------------------------+
1 row in set (0.00 sec) mysql> desc select first_name,min(last_name) from employees group by first_name;+----+-------------+-----------+-------+---------------+-----------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+-----------+---------+------+------+--------------------------+
| 1 | SIMPLE | employees | range | idx_fn_ln | idx_fn_ln | 16 | NULL | 2495 | Using index for group-by |
+----+-------------+-----------+-------+---------------+-----------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
mysql> desc select first_name, last_name from employees group by last_name;
+----+-------------+-----------+-------+---------------+-----------+---------+------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+-------+---------------+-----------+---------+------+--------+----------------------------------------------+
| 1 | SIMPLE | employees | index | idx_fn_ln | idx_fn_ln | 34 | NULL | 299290 | Using index; Using temporary; Using filesort |
+----+-------------+-----------+-------+---------------+-----------+---------+------+--------+----------------------------------------------+
1 row in set (0.01 sec) // mostleftprefix ,创建临时表,filesort
mysql> desc select first_name,last_name from employees where first_name = "Mello" group by last_name;
+----+-------------+-----------+------+---------------+-----------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+-----------+---------+-------+------+--------------------------+
| 1 | SIMPLE | employees | ref | idx_fn_ln | idx_fn_ln | 16 | const | 1 | Using where; Using index |
+----+-------------+-----------+------+---------------+-----------+---------+-------+------+--------------------------+
1 row in set (0.00 sec) // 没有出现using temporary,filesort = > tight index scan
MYSQL GROUP BY Optimization的更多相关文章
- MySQL Group Replication 技术点
mysql group replication,组复制,提供了多写(multi-master update)的特性,增强了原有的mysql的高可用架构.mysql group replication基 ...
- mysql group by 用法解析(详细)
在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...
- (转载)mysql group by 用法解析(详细)
(转载)http://blog.tianya.cn/blogger/post_read.asp?BlogID=4221189&PostID=47881614 mysql distinct 去重 ...
- 细细探究MySQL Group Replicaiton — 配置维护故障处理全集
本文主要描述 MySQL Group Replication的简易原理.搭建过程以及故障维护管理内容.由于是新技术,未在生产环境使用过,本文均是虚拟机测试,可能存在考虑不周跟思路有误 ...
- MySQL Group Replication 动态添加成员节点
前提: MySQL GR 3节点(node1.node2.node3)部署成功,模式定为多主模式,单主模式也是一样的处理. 在线修改已有GR节点配置 分别登陆node1.node2.node3,执行以 ...
- MySQL Group Replication-MGR集群
简介 MySQL Group Replication(简称MGR)字面意思是mysql组复制的意思,但其实他是一个高可用的集群架构,暂时只支持mysql5.7和mysql8.0版本. 是MySQL官方 ...
- mysql group by组内排序
mysql group by组内排序: 首先是组外排序: SELECT z.create_time,z.invoice_id from qf_invoice_log z where z ...
- Docker Images for MySQL Group Replication 5.7.14
In this post, I will point you to Docker images for MySQL Group Replication testing. There is a new ...
- Percona XtraDB Cluster vs Galera Cluster vs MySQL Group Replication
Percona XtraDB Cluster vs Galera Cluster vs MySQL Group Replication Overview Galera Cluster 由 Coders ...
随机推荐
- python科学计算_numpy_ufunc
ufunc简介 ufunc指universal function,是一种能够对数组中的所有元素进行操作的函数,ufunc是针对数组进行操作的函数,对一个数组进行重复的运算时,使用ufunc比math库 ...
- ORA-00600[17059]错误
ORA-00600[17059] ORA-00600[17059]错误大部分都是因为高版本导致,对于本库的分析:因为该库的 shared pool老化比较频繁,到我介入的时候,发现相关该类此sql已经 ...
- linux系统常见压缩命令
在linux环境中,压缩文件的扩展名基本是:*.tar,*.tar.gz,*.tgz,*.gz,*.Z,*.bz2 *.Z compress程序压缩的文件 *.gz gzip程序压缩的文件 *.bz2 ...
- postfix : 452 4.3.1 Insufficient system storage
postfix Error Message: 452 4.3.1 Insufficient system storage --> 空间不足. 但是实际情况是我的各个分区都没有满,只是我的20G ...
- spring中使用Hibernate中的getCurrentSession报出:createQuery is not valid without active transaction
1.错误信息 HTTP Status 500 - createQuery is not valid without active transaction type Exception report m ...
- 为什么很多第三方接口,都改成了基于http,直接传递json数据的方式来代替webservice?
这实际上是三个问题,从WebService到今天流行的RESTful API(JSON) over HTTP,经历了数次变革 1 WebService有很多协议,为什么HTTP比较流行? WebSer ...
- 【Python3之正则re】
一.正则re 1.正则表达式定义 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则.(在Python中)它内嵌在Pytho ...
- jQuery Mobile Slider 禁用点击事件
阿子原创,转载请注明出处. 在使用jQuery Mobile Slider时,发现在页面上下拖动时,很容易不小心触发Slider的点击事件,从而造成误操作.为此需要禁用Slider的点击事件. 官方A ...
- 跟我一起读postgresql源码(九)——Executor(查询执行模块之——Scan节点(上))
从前面介绍的可优化语句处理相关的背景知识.实现思想和执行流程,不难发现可优化语句执行的核心内容是对于各种计划节点的处理,由于使用了节点表示.递归调用.统一接口等设计,计划节点的功能相对独立.代码总体流 ...
- Java 与C++的各种优势与弱点--学习更新中
时隔两年没有怎么碰Java了,最近开始学习回顾下.在这里记录下学习的点滴,持续更新...希望对c++\java等不同语言有较为清晰的认识,至少不要学完以后,哪一个都不会了... Java 优势: 1. ...