由於GROUP BY 實際上也同樣會進行排序操作,而且與ORDER BY 相比,GROUP BY 主要只是多了排序之后的分組操作。當然,如果在分組的時候還使用了其他的一些聚合函數,那么還需要一些聚合函數的計算。所以,在GROUP BY 的實現過程中,與 ORDER BY 一樣也可以利用到索引。

在MySQL 中,GROUP BY 的實現同樣有多種(三種)方式,其中有兩種方式會利用現有的索引信息來完成 GROUP BY,另外一種為完全無法使用索引的場景下使用。下面我們分別針對這三種實現方式做一個分析。

1、使用松散(Loose)索引掃描實現 GROUP BY

何謂松散索引掃描實現 GROUP BY 呢?實際上就是當 MySQL 完全利用索引掃描來實現 GROUP BY 的時候,並不需要掃描所有滿足條件的索引鍵即可完成操作得出結果。

下面我們通過一個示例來描述松散索引掃描實現 GROUP BY,在示例之前我們需要首先調整一下 group_message 表的索引,將 gmt_create 字段添加到 group_id 和 user_id 字段的索引中:

然后再看如下 Query 的執行計划:

我們看到在執行計划的 Extra 信息中有信息顯示“Using index for group-by”,實際上這就是告訴我們,MySQL Query Optimizer 通過使用松散索引掃描來實現了我們所需要的 GROUP BY 操作。

下面這張圖片描繪了掃描過程的大概實現:

要利用到松散索引掃描實現 GROUP BY,需要至少滿足以下幾個條件:

◆GROUP BY 條件字段必須在同一個索引中最前面的連續位置;

◆在使用GROUP BY 的同時,只能使用 MAX 和 MIN 這兩個聚合函數;

◆如果引用到了該索引中 GROUP BY 條件之外的字段條件的時候,必須以常量形式存在;

為什么松散索引掃描的效率會很高?

因為在沒有WHERE子句,也就是必須經過全索引掃描的時候, 松散索引掃描需要讀取的鍵值數量與分組的組數量一樣多,也就是說比實際存在的鍵值數目要少很多。而在WHERE子句包含范圍判斷式或者等值表達式的時候, 松散索引掃描查找滿足范圍條件的每個組的第1個關鍵字,並且再次讀取盡可能最少數量的關鍵字。

2.使用緊湊(Tight)索引掃描實現 GROUP BY

緊湊索引掃描實現 GROUP BY 和松散索引掃描的區別主要在於他需要在掃描索引的時候,讀取所有滿足條件的索引鍵,然后再根據讀取惡的數據來完成 GROUP BY 操作得到相應結果。

這時候的執行計划的 Extra 信息中已經沒有“Using index for group-by”了,但並不是說 MySQL 的 GROUP BY 操作並不是通過索引完成的,只不過是需要訪問 WHERE 條件所限定的所有索引鍵信息之后才能得出結果。這就是通過緊湊索引掃描來實現 GROUP BY 的執行計划輸出信息。

下面這張圖片展示了大概的整個執行過程:

在 MySQL 中,MySQL Query Optimizer 首先會選擇嘗試通過松散索引掃描來實現 GROUP BY 操作,當發現某些情況無法滿足松散索引掃描實現 GROUP BY 的要求之后,才會嘗試通過緊湊索引掃描來實現。

當 GROUP BY 條件字段並不連續或者不是索引前綴部分的時候,MySQL Query Optimizer 無法使用松散索引掃描,設置無法直接通過索引完成 GROUP BY 操作,因為缺失的索引鍵信息無法得到。但是,如果 Query 語句中存在一個常量值來引用缺失的索引鍵,則可以使用緊湊索引掃描完成 GROUP BY 操作,因為常量填充了搜索關鍵字中的“差距”,可以形成完整的索引前綴。這些索引前綴可以用於索引查找。而如果需要排序GROUP BY結果,並且能夠形成索引前綴的搜索關鍵字,MySQL還可以避免額外的排序操作,因為使用有順序的索引的前綴進行搜索已經按順序檢索到了所有關鍵字。

3.使用臨時表實現 GROUP BY

MySQL 在進行 GROUP BY 操作的時候要想利用所有,必須滿足 GROUP BY 的字段必須同時存放於同一個索引中,且該索引是一個有序索引(如 Hash 索引就不能滿足要求)。而且,並不只是如此,是否能夠利用索引來實現 GROUP BY 還與使用的聚合函數也有關系。

前面兩種 GROUP BY 的實現方式都是在有可以利用的索引的時候使用的,當 MySQL Query Optimizer 無法找到合適的索引可以利用的時候,就不得不先讀取需要的數據,然后通過臨時表來完成 GROUP BY 操作。

這次的執行計划非常明顯的告訴我們 MySQL 通過索引找到了我們需要的數據,然后創建了臨時表,又進行了排序操作,才得到我們需要的 GROUP BY 結果。整個執行過程大概如下圖所展示:

當 MySQL Query Optimizer 發現僅僅通過索引掃描並不能直接得到 GROUP BY 的結果之后,他就不得不選擇通過使用臨時表然后再排序的方式來實現 GROUP BY了。

在這樣示例中即是這樣的情況。 group_id 並不是一個常量條件,而是一個范圍,而且 GROUP BY 字段為 user_id。所以 MySQL 無法根據索引的順序來幫助 GROUP BY 的實現,只能先通過索引范圍掃描得到需要的數據,然后將數據存入臨時表,然后再進行排序和分組操作來完成 GROUP BY。

mysql 分组查询原理,MySQL分組查詢Group By實現原理詳解相关推荐

  1. oracle 按日输出 取整数,Oracle按日周月分組統計,及next_day()函數詳解

    1.概述 工作中遇到如下問題:統計周期內關鍵詞數,而這里的周期內最常用的就是日周月. 日月比較容易處理,周的話可以通過next_day()函數實現. 2.實例問題 如下,有一張表ljb_test,包括 ...

  2. mysql分组查询学生平均年龄_MySQL学习-基础练习题

    day1 学生表操作: 1. 查询出班级205有多少个男生 2. 查询出名字为4个字的所有学生信息(编号.姓名,年龄,班级) 3. 查询出所有姓王的学生信息(编号.姓名,年龄,班级) 4. 查询出班级 ...

  3. mysql分组查询和分组过滤

    mysql分组查询使用的的关键字是group by,分组过滤使用到的关键字是having.需要先分组查询才能进行分组过滤,个人理解having和where的区别有以下: 1.聚集函数count.sum ...

  4. mysql分頁查詢_mysql分頁查詢 | 學步園

    MySQL中一般的分頁作法大多利用Limit限制回傳的資料筆數來達成分頁效果 例如下面的代碼 Select * From news limit 0, 100第一頁 Select * From news ...

  5. mysql 分组查询最新

    mysql分组查询最新 看到网上说到的方法和我写的都一样,也不知道有没有更好的方法,等到解答. SELECT id,group_id from (SELECT id,group_id from tab ...

  6. Mysql分组查询每组最新的一条数据(三种实现方法)

    MySQL分组查询每组最新的一条数据 前言 注意事项 准备SQL 错误查询 错误原因 方法一 方法二(适用于自增ID和创建时间排序一致) 方法三(适用于自增ID和创建时间排序一致) 总结 MAX()函 ...

  7. MySQL分组查询,获取分组后数据

    MySQL分组查询,获取分组后数据 MySQL分组查询,将其它列的数据,合并到一行展示,可以设置去重,设置去重,设置排序,截取指定条数 创建表结构 CREATE TABLE `author_info` ...

  8. MySQL数据处理函数,分组函数,分组查询【MySQL】

    Java养成计划----学习打卡第六十六天 内容导航 单行处理函数(续) CONCAT 字符串拼接函数 LENGTH 字符串长度 TRIM 去空格 ROUND 四舍五入 RAND 生成随机数 IFNU ...

  9. MySQL分组查询跟聚合函数

    MySQL分组查询跟聚合函数 一.分组查询的语句 GROUP BY { <列名> | <表达式> | <位置> } [ASC | DESC] 这个语句中间{ < ...

最新文章

  1. ssm插入数据时候栈溢出_大话数据结构笔记(4)
  2. CAMWorks ShopFloor 2020中文版
  3. javascript之作用域
  4. 常量、变量、数据类型
  5. Python 3.6学习笔记(一)
  6. python xyz_python中xyz坐标的欧几里德距离
  7. ❤️❤️❤️【资料免费领取】简历模板、职场PPT模板、硬核学习资料+PDF资料(Java、Python、大数据、机器学习)❤️❤️❤️
  8. 虚拟化与私有云的区别
  9. Safari技术预览版141来啦,增加了哪些新功能?
  10. mysql服务器的字符集
  11. CSS 属性篇(六):background-size属性
  12. 你想要的宏基因组-微生物组知识全在这(2022.8)
  13. 游戏植入广告获取收益
  14. C++如何判断一个程序是 死锁 还是 死循环,如何进行问题定位与分析
  15. 1月16日云栖精选夜读 | 阿里P8架构师谈:Zookeeper的原理和架构设计,以及应用场景... 1
  16. one choise or a complain
  17. LOE是什么?如何加入?
  18. 【Python+QGIS将地名批量标注于高德地图】
  19. 我的U盘终于中招啦:U盘快捷方式病毒
  20. 办公室常见问题解决:不能连接局域网的共享打印机

热门文章

  1. webservie报文格式
  2. SpringBoot2.x整合quartz定时任务 快速入门
  3. Apache JMeter 菜单说明
  4. idea 暂存文件或idea切换分支代码不见了
  5. JavaScript从入门到放弃 -(五)函数进阶(高级用法)
  6. 适用于ios和android,适用于iOS和Android的OpenGL ES差异
  7. 8s存储最佳方案_MaxiDi, 意大利:自动化物流解决方案
  8. java并发编程代码示例_java并发编程之同步器代码示例
  9. linux磁盘资源,liunxCPU和内存,磁盘等资源,
  10. 语言速算24点的小窍门_4秒钟1道题!12岁少年三夺24点大赛冠军