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;
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的更多相关文章

  1. MySQL Group Replication 技术点

    mysql group replication,组复制,提供了多写(multi-master update)的特性,增强了原有的mysql的高可用架构.mysql group replication基 ...

  2. mysql group by 用法解析(详细)

    在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供 有distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...

  3. (转载)mysql group by 用法解析(详细)

    (转载)http://blog.tianya.cn/blogger/post_read.asp?BlogID=4221189&PostID=47881614 mysql distinct 去重 ...

  4. 细细探究MySQL Group Replicaiton — 配置维护故障处理全集

             本文主要描述 MySQL Group Replication的简易原理.搭建过程以及故障维护管理内容.由于是新技术,未在生产环境使用过,本文均是虚拟机测试,可能存在考虑不周跟思路有误 ...

  5. MySQL Group Replication 动态添加成员节点

    前提: MySQL GR 3节点(node1.node2.node3)部署成功,模式定为多主模式,单主模式也是一样的处理. 在线修改已有GR节点配置 分别登陆node1.node2.node3,执行以 ...

  6. MySQL Group Replication-MGR集群

    简介 MySQL Group Replication(简称MGR)字面意思是mysql组复制的意思,但其实他是一个高可用的集群架构,暂时只支持mysql5.7和mysql8.0版本. 是MySQL官方 ...

  7. mysql group by组内排序

    mysql group by组内排序:     首先是组外排序:     SELECT z.create_time,z.invoice_id from qf_invoice_log z where z ...

  8. 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 ...

  9. Percona XtraDB Cluster vs Galera Cluster vs MySQL Group Replication

    Percona XtraDB Cluster vs Galera Cluster vs MySQL Group Replication Overview Galera Cluster 由 Coders ...

随机推荐

  1. 前端学习_01_css网页布局

    引子 之前也自己陆陆续续地学了一些web方面的知识,包括前段和后端都有涉及到,自己也比较感兴趣,感谢peter老师,愿意无偿提供从零开始的教学,之前也看过peter老师的一些视频,节奏非常适合我,决心 ...

  2. 更加清楚理解mvc结构

      更加清楚理解mvc结构 文章来源:刘俊涛的博客 地址:http://www.cnblogs.com/lovebing 欢迎关注,有问题一起学习欢迎留言.评论.

  3. Redis锁构造

    单线程与隔离性 Redis是使用单线程的方式来执行事务的,事务以串行的方式运行,也就是说Redis中单个命令的执行和事务的执行都是线程安全的,不会相互影响,具有隔离性. 在多线程编程中,对于共享资源的 ...

  4. MicroPython教程之TPYBoard v102 CAN总线通信

    0x00前言 CAN是控制器局域网络(ControllerAreaNetwork,CAN)的简称,是ISO国际标准化的串行通信协议.CAN总线结构简单,只需2根线与外部相连,并且内部集成了错误探测和管 ...

  5. angular4.0如何引入外部插件2:declare方案

    前面有个<angular4.0如何引入外部插件1:import方案>,但是有局限,因为方案1需要用到@types这个东西. 但是并不是每一个插件都有@types,所以现在写个方案2. 拿引 ...

  6. iPhone X 适配

    背景 iPhone X 刘海机于9月13日发布,给科技小春晚带来一波高潮.作为开发人员却多出来一份忧虑,iPhone X 怎么适配?我们 App 的脑袋会不会也长一刘海出来?Tabbar 会不会被圆角 ...

  7. [Spark内核] 第36课:TaskScheduler内幕天机解密:Spark shell案例运行日志详解、TaskScheduler和SchedulerBackend、FIFO与FAIR、Task运行时本地性算法详解等

    本課主題 通过 Spark-shell 窥探程序运行时的状况 TaskScheduler 与 SchedulerBackend 之间的关系 FIFO 与 FAIR 两种调度模式彻底解密 Task 数据 ...

  8. 【整理】REACT一些自己感觉需要记的东西

    REACT生命周期: 组件的生命周期可分成三个状态: Mounting:已插入真实 DOM Updating:正在被重新渲染 Unmounting:已移出真实 DOM 生命周期的方法有: compon ...

  9. RequireJS对文件合并与压缩实现方法

    RequireJS 是一个JavaScript模块加载器.它非常适合在浏览器中使用, 它非常适合在浏览器中使用,但它也可以用在其他脚本环境, 就像 Rhino and Node. 使用RequireJ ...

  10. 常用OJ名字+地址(自用)

    常用OJ名字+地址 不定期更新,自己用,有补充的也可以给我说说哈. 中文 openjudge 地址:openjudge.cn 说明:北大提供的一个平台,学校可申请小组: 比较好的小组: 计算概论:ic ...