一篇文章了解MySQL的group by

news2024/11/13 9:03:27

准备工作!

1.本文章MySQL使用的是5.7,引擎使用的是innodb
2. 使用的表结构(t1),字段a上有一个索引,
在这里插入图片描述

1. group by常用方法:

group by的常规用法是配合聚合函数,利用分组信息进行统计,常见的是配合max等聚合函数筛选数据后分析,以及配合having进行筛选后过滤。
聚合函数

  • count(),返回指定列中数据的个数
  • sum(),返回指定列中数据的总和
  • avg(),返回指定列中数据的平均值
  • min(),返回指定列中数据的最小值
  • max(),返回指定列中数据的最大值

示例1: 查询t1表,按照字段b进行分组,并求出分组后b字段a的总和。

SELECT  MAX(a) from t1 GROUP BY b

实例2:查询t1表,按照字段b进行分组,拿到b<100的所有数据,求出a的总和。

SELECT  MAX(a) from t1 GROUP BY b HAVING b<100

where和having区别

where子句将单个行过滤到查询结果中,而having子句将分组过滤到查询结果中 having子句中使用的列名必须出现在group by子句列表中,或包括在聚集函数中。

having子句的条件运算至少包括一个聚集函数,否则可以把查询条件移到where字句中来过滤单个行(注意聚集函数不可以用在where子句中)


2. group by语句执行流程:

我们执行以下语句

SELECT  b, count(*) as c from t1 GROUP BY b HAVING b<100

查看explain执行情况,由于b字段上没有索引,所以进行全表扫描。
在这里插入图片描述

Using temporary; 表示使用了临时表;
Using filesort ,表示需要排序。

由于字段b上没有索引,它的执行顺序是这样的

  • 创建内存临时表,表里有两个字段 b 和 c,主键是 b;
  • 对t1表进行全表扫描,并取出第一条数据,判断b是否小于100。如果b<100,就记录b的值为X,并存入临时表。
    1.如果临时表中没有主键为b的行,就插入一条记录 b,c(x,1)
    2.如果临时表中有主键为b的行,就更新主键为b的这一行,并把c的值进行加1
  • 遍历完成后,再根据字段 b做排序,得到结果集返回给客户端。

在MySQL当中排序有两种
第一种是 全字段排序 ,第二种是 rowid 排序。 具体可以通过我的这篇文章去了解一篇文章搞懂MySQL的order by


3.使用group by会有哪些问题:

我们执行以下语句

SELECT  b, count(*) as c from t1 GROUP BY b HAVING b<100

在上述中,由于b字段没有索引,索引MySQL默认会对此语句进行排序。相信你也看了我的一篇文章搞懂MySQL的order by这篇文章,也了解了MySQL什么时候会用全字段排序,什么时候用 rowid 排序。

1. 使用磁盘临时文件进行排序

在此语句中,优化器使用的是全字段排序,那么使用全字段排序会有哪些问题?
在全字段排序中,它是通过sort_buffer进行排序,定义如下。

sort_buffer_size:就是 MySQL 为排序开辟的内存(sort_buffer)的大小。如果要排序的数据量小于sort_buffer_size,排序就在内存中完成。但如果排序数据量太大,内存放不下,则不得不利用磁盘临时文件辅助排序。

假如我们如下SQL语句查出有1亿行,这时由于我们查询数据大小超过了定义的 临时排序文件( sort_buffer_size)的大小时,

SELECT  b, count(*) as c from t1 GROUP BY b HAVING b<100000000

那么,这时就需要使用外部排序,外部排序一般使用归并排序算法。可以这么简单理解,MySQL 将需要排序的数据分成 n份,每一份单独排序后存在这些临时文件中。然后把这n个有序文件再合并成一个有序的大文件。由于分成的的临时文件很多,就会造成排序的性能很差。


2. 查询数据超过临时文件大小(tmp_table_size)

这个例子里由于临时表只有 100 行,内存可以放得下,因此全程只使用了内存临时表。但是,内存临时表的大小是有限制的,参数 tmp_table_size 就是控制这个内存大小的,默认是 16M。接下来我把tmp_table_size大小改成1kb。

假如我们如下SQL语句查出有1亿行,这时由于我们查询数据大小超过了定义的 临时文件( tmp_table_size)的大小时。

SELECT  b, count(*) as c from t1 GROUP BY b HAVING b<100000000

那么,这时就会把内存临时表转成磁盘临时表(磁盘临时表默认使用的引擎是 InnoDB)。由于我们数据量很大,很可能这个查询需要的磁盘临时表就会占用大量的磁盘空间。


4.group by的优化方法:

我们还是以这条SQL语句为准

SELECT  b, count(*) as c from t1 GROUP BY b HAVING b<100

1. 如果你的需求并不需要对结果进行排序,那你可以在 SQL 语句末尾增加 order by null

explain SELECT  b, count(*) as c from t1 GROUP BY b HAVING b<100 ORDER BY null 

查看explain 结果在这里插入图片描述

Using temporary; 表示使用了临时表;


2. 可以对group by字段建立索引

众所周知,由于我们MySQL的InnoDB引擎使用的数据结构是B+树,而B+树相比于B树最显著的特征就是B+树叶子节点是一个有序的双向列表。既然他已经有序了,那么我们是不是可以直接不进行排序了。

我们执行以下SQL语句,并在字段b上建立索引

SELECT  b, count(*) as c from t1 GROUP BY b HAVING b<100

查看explain执行情况,没有进行排序,没有使用临时文件
在这里插入图片描述

Using index;使用了覆盖索引。
由于字段b上有索引,它的执行顺序是这样的

在这里插入图片描述

执行流程:

  • 扫描t1表的索引b,读取磁盘块1,将磁盘块加载到内存中判断50是否小于100,是就走左边,不是就走右边。

  • 扫描磁盘块2,将磁盘块加载到内存中判断判断30是否小于100,是就走左边,不是就走右边。

  • 读取磁盘块3,将磁盘块加载到内存中判断判断20是否小100,是就走左边,不是就走右边。

  • 读取磁盘块4也就是叶子节点,它是一个有序的链表。从键值10开始向后遍历筛选所有符合筛选条件的数据,并将符合筛选条件的data值数据缓存到结果集。(因为是双向有序的,所以会依次读取,并不需要回到父节点。因此当读取到20后会直接读取磁盘块5)
    1.当碰到第一个 10 的时候,结果集里的第一行就是 (10,1);
    2.当碰到第二个 10 的时候,已经知道累积了 1 个 10,修改结果集里的第一行为(10,2);

  • 当依次读取导磁盘块12后,将磁盘块加载到内存中判断100是否小于100,不是;就不需再向后查找,查询终止。将结果集返回给用户。

因此当我们扫描到整个输入的数据结束,就可以拿到 group by 的结果,不需要临时表,也不需要再额外排序


3. group by字段无法建立索引时

如果可以通过加索引来完成 group by 逻辑就再好不过了。但是,如果碰上不适合创建索引的场景,我们还是要老老实实做排序的。那么,这时候的 group by 要怎么优化呢?

如果我们明明知道,一个 group by语句中需要放到临时表上的数据量特别大,却还是要按照“先放到内存临时表,插入一部分数据后,发现内存临时表不够用了再转成磁盘临时表”,这样看上去就有点儿傻。

我们执行以下SQL语句,并使用 SQL_BIG_RESULT(SQL_BIG_RESULT告诉mysql的分组语句必须使用磁盘临时表)

SELECT  SQL_BIG_RESULT b, count(*) as c from t1 GROUP BY b HAVING b<100

查看explain执行情况
在这里插入图片描述
Using filesort 表示需要排序。

执行流程:

  • .初始化 sort_buffer,确定放入一个整型字段,记为 b;
  • . 扫描表 t1 ,依次取出里面b<100的值, 将b的值存入 sort_buffer 中;
  • . 扫描完成后,对 sort_buffer 的字段 b 做排序(如果 sort_buffer 内存不够用,就会利用磁盘临时文件辅助排序);
  • . 排序完成后,就得到了一个有序数组。

在根据有序数组,得到数组里面的不同值,以及每个值的出现次数。


5. MySQL8.0之后版本的group by

我们还是以这条SQL语句为准(MySQL版本8.0.26)

SELECT  b, count(*) as c from t1 GROUP BY b HAVING b<100

查看explain执行情况
在这里插入图片描述
Using temporary; 表示使用了临时表;

group by 在 MySQL5.7 版本会自动排序,但是在MySQL8 .0之后版本就去掉了自动排序功能。


6.总结

1.如果对 group by 语句的结果没有排序要求,要在语句后面加 order by null;

2.尽量让 group by 过程用上表的索引,确认方法是 explain 结果里没有 Using temporary 和 Using filesort;

3.如果 group by 需要统计的数据量不大,尽量只使用内存临时表;也可以通过适当调大 tmp_table_size 参数,来避免用到磁盘临时表;

4.如果数据量实在太大,使用 SQL_BIG_RESULT 这个提示,来告诉优化器直接使用排序算法得到 group by 的结果。

5.group by 在 MySQL5.7 版本会自动排序,但是在MySQL8 .0之后版本就去掉了排序功能。


在这里插入图片描述

今晚我支持总监,法国冲冲冲!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/60645.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

公众号网课查题接口使用方法

公众号网课查题接口使用方法 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 题库&#xff1a;题库后台&#xff08;点击跳转&…

用Hopper修改代理软件端口

背景 用代理软件可以访问google&#xff0c;但是端口经常不固定&#xff0c;从缺省1080变成了随机。 前几天其实已经用Hopper 3.0看了一次&#xff0c;但是好像不支持go&#xff0c;所以没反编译成功&#xff0c;这次换了4.0&#xff0c;支持了go。 Hopper与逆向 逆向的目的…

7.7 网络(二)

接上篇&#xff1a;7.7 网络&#xff08;一&#xff09;_龙赤子的博客-CSDN博客 目录 三 操作系统涉及的网络内容 1 网络栈 2 协议 3 应用 三 操作系统涉及的网络内容 1 网络栈 这里我们重点讨论操作系统里面的网络。这部分在整个网络架构中&#xff0c;属于端的技术。对于端来…

Spring - ApplicationContextAwareProcessor扩展接口

文章目录Preorg.springframework.context.support.ApplicationContextAwareProcessor内部的7个扩展点源码解析扩展示例Pre Spring Boot - 扩展接口一览 org.springframework.context.support.ApplicationContextAwareProcessor /** Copyright 2002-2020 the original author …

python中xpath解析

**前言&#xff1a;**今年博客更新的太少了&#xff0c;很多学习计划都因为工作原因延迟了&#xff0c;今年真的身心太疲惫了&#xff0c;终于有点能理解为什么有的同行们会无心学习了&#xff0c;今年同样也是吃老本的一篇博客&#xff0c;所谓好记性不如烂笔头&#xff0c;以…

Java中静态域和静态方法的一些梳理

最近发现自己对一些Java中的静态域和静态方法的基础知识掌握的不是特别牢靠&#xff0c;于是针对一些自己之前模棱两可的点&#xff0c;进行书籍的翻阅复习。 参考文献&#xff1a; Java核心技术卷一 静态域 将域定义为static&#xff0c;代表该类的所有实例对象都共享这一个…

[附源码]计算机毕业设计JAVA医药管理系统

[附源码]计算机毕业设计JAVA医药管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis M…

QT5.14.2+cmake3.8.2+opencv3.4.0环境配置遇到的问题

1、cmke的configure时遇到无法下载opencv_ffmpeg.dll等三个文件 我直接用网上的下载好的在文件夹中添加&#xff0c;不过&#xff0c;一定要改成原文件的命名&#xff0c;就是带一堆数字签名的&#xff1a; 然后直接Generate,之后就可以去cmd编译了 &#xff08;因为再次conf…

RocketMq消息持久化(一)——存储架构设计概述

1.RocketMq 存储概要设计 RocketMQ主要存储的文件包括Comitlog文件、ConsumeQueue文件、IndexFile文件&#xff0c;存储路径为${ROCKET_HOME}/store&#xff0c;默认在当前用户目录下的store目录&#xff1a; store目录下的文件如上所示&#xff0c;分别有&#xff1a;checkpo…

[附源码]计算机毕业设计JAVA医院床位管理系统

[附源码]计算机毕业设计JAVA医院床位管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybati…

Halo搭建个人博客网站

Halo搭建个人博客网站 一、docker部署Halo 目前测试了两种方法安装Halo&#xff0c;第一种是使用Jar包安装:提供JAR包资源&#xff0c;不过因为使用jar包部署需要Java11才可以&#xff0c;我本机使用的是Java8&#xff0c;所以暂时不做调整。第二种是通过docker安装。 1.1 启…

项目实例:H3C端口镜像 (镜像单目的端口 镜像多目的端口)

一、项目实例 某局业务系统三级等保项目&#xff1a;配置只列出端口镜像部分&#xff0c;其他部分及设备&#xff08;略&#xff09; 1.1 边界部署两台防火墙做HA高可用 1.2 核心使用两台H3C交换机做堆叠&#xff0c;上联线路分别连接防火墙&#xff08;主&#xff09;、防火…

【Python自然语言处理】隐马尔可夫模型中维特比(Viterbi)算法解决商务选择问题实战(附源码 超详细必看)

需要源码请点赞关注收藏后评论区留言私信~~~ 一、统计分词 统计分词基本逻辑是把每个词语看做由单字组成&#xff0c;利用统计学原理计算连接字在不同文本中出现的次数&#xff0c;以此判断相连字属于特定词语的概率。 二、隐马尔可夫模型 当一个随机过程在给定现在状态及所…

计算机组成详解(运算器、控制器、存储器、I/O部件)

文章目录1 概述1.1 计算机组成图2 三大部件2.1 中央处理器 CPU运算器 ALU控制器 CU2.2 内存储器2.3 输入输出设备3 扩展3.1 计算机系统结构图1 概述 1.1 计算机组成图 2 三大部件 2.1 中央处理器 CPU 运算器 ALU 运算器 ALU&#xff1a;Arithmetic Logic Unit&#xff0c;算…

游泳可以戴的耳机有哪些、推荐几款真正能戴着游泳的蓝牙耳机

现在身边很多人也是非常喜欢游泳&#xff0c;尤其是到了夏天的时候&#xff0c;这项运动可以消耗体内多余脂肪&#xff0c;起到很好的强身健体的作用&#xff0c;比其跑步来说有着明显的优势。不过想要转移游泳带来的疲惫&#xff0c;那么在水里面听听激情的音乐是必不可少的&a…

DAY04-网页布局实战常用HTML标签完整盒模型

文章目录网页布局实战一 HTML标签二 布局标签三 文本标签1文字标签2 列表3 图片标签4 超连接5 相对路径与绝对路径四 行和块的区分五 行和块的转换六 标准盒模型外边距内边距边框盒子模式七 案例网页布局实战 一 HTML标签 HTML的标签分为两类&#xff1a; 布局标签&#xff…

springboot中使用Spring Data Jpa

Springboot 中如何集成spring data jpa 一 什么是ORM&#xff1f; ORM即Object-Relationl Mapping&#xff0c;它的作用是在关系型数据库和对象之间作一个映射&#xff0c;这样&#xff0c;我们在具体的操作数据库的时候&#xff0c;就不需要再去和复杂的SQL语句打交道&#…

图论期末复习(《图论机器应用》——朴月华)

文章目录一、图的基本概念二、图的连通性三、树四、E 图与 H 图五、对集与独立集六、平面图与网络流一、图的基本概念 1、基本概念2、顶点的度 概念&#xff0c;有关定理及推论&#xff08;握手定理&#xff09;&#xff0c;度序列的概念及相关结论&#xff0c;根据度序列画图…

【星球】【slam】 研讨会(5)VINS:Mono+Fusion 重点提炼

VINSFusion重点梳理 A重点梳理和回顾 1传感器前端 视觉前端 特征点提取 opencv接口 goodfeaturestotrack 光流追踪 opencv接口 calcOptical 异常点剔除 光流剔除的异常点 本质矩阵的校验(不符合本质矩阵的点筛除) 特征点去畸变 “逐渐逼近式”的计算方式 特征点性质的计算 IM…

常用算法-Java

基础概念 程序 数据结构 算法 算法特性&#xff1a;输入、输出、有穷性、确定性、可靠性 算法目标&#xff1a;正确性、可读性、健壮性、运行时间少、内存空间小 时间复杂度 时间复杂度是用来估计算法运行时间的一个单位。 一般来说&#xff0c;时间复杂度高的算法比时…