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数量,需要满足以下几点:

1:该查询只覆盖一个表,

2:group by子句中的列属性满足最左前缀原则,并且没有别的非index中的列属性。(instinct关键字也通用适用),e.g. 表t1 有一个index(c1,c2,c3),如果查询含有group by              c1,c2,则loose index sacn是合适的,但group by c2,c3则不合适(最左前缀),group by c1,c2,c4也不合适(c4不为该index中的列属性)。

3:select子句中的列属性只能包含min(),max()聚合函数,并且它们都引用group by中一个列属性。

4:查询语句中的index关键字(except group by子句的那些index关键字)必须为常量(意味着,他们必须通过 = constra的形式被引用),除非是min(),max();

5:index中所有列关键字,列值必须完整索引,而不是一个前缀索引,e.g. c1 varchar(20), index (c1(10)),该索引不会被loose index scan使用。

查询语句使用loose index scan时, explain输出 Using index for group-by信息;

假设在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;
时间: 2024-10-08 13:45:16

MYSQL GROUP BY Optimization的相关文章

Mysql group by top N的问题

在日常工作中,经常要查询分组的前几名.oracle中可以通过row_num来支持查询,mysql暂时不支持row_num.那么如何来完成这个需求呢? 例如: 表中的数据: +--------+-------+-----+ | Person | Group | Age | +--------+-------+-----+ | Bob | 1 | 32 | | Jill | 1 | 34 | | Shawn | 1 | 42 | | Jake | 2 | 29 | | Paul | 2 | 36 |

MySQL group replication介绍

"MySQL group replication" group replication是MySQL官方开发的一个开源插件,是实现MySQL高可用集群的一个工具.第一个GA版本正式发布于MySQL5.7.17中:想要使用group replication只需要从官网上下载MySQL5.7.17及以后的版本即可 group replication发布以后,有3种方法来实现MySQL的高可用集群: ①:异步复制 ②:半同步复制 ③:group replication ---注意: 异步复制是

mysql group by 用法解析(详细)

在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的所有值.其原因是 distinct只能返回它的目标字段,而无法返回其它字段,这个问题让我困扰了很久,用distinct不能解决的话,我只有用二重循环查询来解决,而 这样对于一个数据量非常大的站来说,无疑是会直接影响到效率的.所以我花了很多时间来研究这个问题,网上也查不到解决方案 下面先来看看例子:

MySQL Group Replication调研剖析

一.MySQL复制的三种模式 MySQL当前存在的三种复制模式有:异步模式.半同步模式和组复制模式,先了解一下三种模式的工作方式. 1.MySQL Asynchronous Replication(异步复制) 异步复制是MySQL最早的也是当前使用最多的复制模式,异步复制提供了一种简单的主-从复制方法,包含一个主库(master)和备库(一个,或者多个)之间,主库执行并提交了事务,在这之后(因此才称之为异步),这些事务才在从库上重新执行一遍(基于statement)或者变更数据内容(基于row)

Mysql Group Replication 简介及单主模式组复制配置【转】

一 Mysql Group Replication简介 Mysql Group Replication(MGR)是一个全新的高可用和高扩张的MySQL集群服务. 高一致性,基于原生复制及paxos协议的组复制技术,以插件方式提供一致数据安全保证: 高容错性,大多数服务正常就可继续工作,自动不同节点检测资源征用冲突,按顺序优先处理,内置自动防脑裂机制: 高扩展性,自动添加移除节点,并更新组信息: 高灵活性,单主模式和多主模式.单主模式自动选主,所有更新操作在主进行:多主模式,所有server同时更

mysql group by的特殊性

SELECT create_year, userno , sum(sal) FROM user GROUP BY userno 以上语句,在oracle 或sql server肯定是语法错误  因为group by 少了 create_year,在mysql中却能正常执行, 因为: mysql group by userno类似去重复,默认保留create_year第一条,所以保留的是by userno下面create_year第一条,记录的sum(sal) 参考:http://zhidao.b

MySQL GROUP BY 语句

MySQL GROUP BY 语句 GROUP BY 语句根据一个或多个列对结果集进行分组. 在分组的列上我们可以使用 COUNT, SUM, AVG,等函数. GROUP BY 语法 SELECT column_name, function(column_name) FROM table_name WHERE column_name operator value GROUP BY column_name; 实例演示 本章节实例使用到了以下表结构及数据,使用前我们可以先将以下数据导入数据库中.

Mysql Group Replication 简析

前段时间做了组内分享,写的关于mysql Group Replication 文章   3, 高扩展 原文地址:https://www.cnblogs.com/yhdgm/p/8124719.html

mysql group by 对多个字段进行分组

mysql group by 对多个字段进行分组 group by X 意思是将所有具有相同X字段值的记录放到一个分组里. 那么group by  X, Y呢? group by X, Y意思是将所有具有相同X字段值和Y字段值的记录放到一个分组里. 原文地址:https://www.cnblogs.com/beiyi888/p/9623257.html