0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

为什么在语义相同的情况下group by和distinct效率相同呢?

jf_ro2CN3Fa 来源:CSDN 2023-01-09 10:46 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

结论

先说大致的结论:

在语义相同,有索引的情况下:group by和distinct都能使用索引,效率相同。

在语义相同,无索引的情况下:distinct效率高于group by。原因是distinct 和 group by都会进行分组操作,但group by可能会进行排序,触发filesort,导致sql执行效率低下。

基于这个结论,你可能会问:

为什么在语义相同,有索引的情况下,group by和distinct效率相同?

在什么情况下,group by会进行排序操作?

带着这两个问题找答案。接下来,我们先来看一下distinct和group by的基础使用。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

distinct的使用

distinct用法

SELECTDISTINCTcolumnsFROMtable_nameWHEREwhere_conditions;

例如:

mysql>selectdistinctagefromstudent;
+------+
|age|
+------+
|10|
|12|
|11|
|NULL|
+------+
4rowsinset(0.01sec)

DISTINCT 关键词用于返回唯一不同的值。放在查询语句中的第一个字段前使用,且作用于主句所有列。

如果列具有NULL值,并且对该列使用DISTINCT子句,MySQL将保留一个NULL值,并删除其它的NULL值,因为DISTINCT子句将所有NULL值视为相同的值。

distinct多列去重

distinct多列的去重,则是根据指定的去重的列信息来进行,即只有所有指定的列信息都相同,才会被认为是重复的信息。

SELECTDISTINCTcolumn1,column2FROMtable_nameWHEREwhere_conditions;
mysql>selectdistinctsex,agefromstudent;
+--------+------+
|sex|age|
+--------+------+
|male|10|
|female|12|
|male|11|
|male|NULL|
|female|11|
+--------+------+
5rowsinset(0.02sec)

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

group by的使用

对于基础去重来说,group by的使用和distinct类似:

单列去重

语法:

SELECTcolumnsFROMtable_nameWHEREwhere_conditionsGROUPBYcolumns;

执行:

mysql>selectagefromstudentgroupbyage;
+------+
|age|
+------+
|10|
|12|
|11|
|NULL|
+------+
4rowsinset(0.02sec)

多列去重

语法:

SELECTcolumnsFROMtable_nameWHEREwhere_conditionsGROUPBYcolumns;

执行:

mysql>selectsex,agefromstudentgroupbysex,age;
+--------+------+
|sex|age|
+--------+------+
|male|10|
|female|12|
|male|11|
|male|NULL|
|female|11|
+--------+------+
5rowsinset(0.03sec)

区别示例

两者的语法区别在于,group by可以进行单列去重,group by的原理是先对结果进行分组排序,然后返回每组中的第一条数据。且是根据group by的后接字段进行去重的。

例如:

mysql>selectsex,agefromstudentgroupbysex;
+--------+-----+
|sex|age|
+--------+-----+
|male|10|
|female|12|
+--------+-----+
2rowsinset(0.03sec)

distinct和group by原理

在大多数例子中,DISTINCT可以被看作是特殊的GROUP BY,它们的实现都基于分组操作,且都可以通过松散索引扫描、紧凑索引扫描(关于索引扫描的内容会在其他文章中详细介绍,就不在此细致介绍了)来实现。

DISTINCT和GROUP BY都是可以使用索引进行扫描搜索的。例如以下两条sql(只单单看表格最后extra的内容),我们对这两条sql进行分析,可以看到,在extra中,这两条sql都使用了紧凑索引扫描Using index for group-by。

所以,在一般情况下,对于相同语义的DISTINCT和GROUP BY语句,我们可以对其使用相同的索引优化手段来进行优化。

mysql>explainselectint1_indexfromtest_distinct_groupbygroupbyint1_index;
+----+-------------+-----------------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|
+----+-------------+-----------------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|1|SIMPLE|test_distinct_groupby|NULL|range|index_1|index_1|5|NULL|955|100.00|Usingindexforgroup-by|
+----+-------------+-----------------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
1rowinset(0.05sec)

mysql>explainselectdistinctint1_indexfromtest_distinct_groupby;
+----+-------------+-----------------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|
+----+-------------+-----------------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|1|SIMPLE|test_distinct_groupby|NULL|range|index_1|index_1|5|NULL|955|100.00|Usingindexforgroup-by|
+----+-------------+-----------------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
1rowinset(0.05sec)

但对于GROUP BY来说,在MYSQL8.0之前,GROUP Y默认会依据字段进行隐式排序。

可以看到,下面这条sql语句在使用了临时表的同时,还进行了filesort。

mysql>explainselectint6_bigger_randomfromtest_distinct_groupbyGROUPBYint6_bigger_random;
+----+-------------+-----------------------+------------+------+---------------+------+---------+------+-------+----------+---------------------------------+
|id|select_type|table|partitions|type|possible_keys|key|key_len|ref|rows|filtered|Extra|
+----+-------------+-----------------------+------------+------+---------------+------+---------+------+-------+----------+---------------------------------+
|1|SIMPLE|test_distinct_groupby|NULL|ALL|NULL|NULL|NULL|NULL|97402|100.00|Usingtemporary;Usingfilesort|
+----+-------------+-----------------------+------------+------+---------------+------+---------+------+-------+----------+---------------------------------+
1rowinset(0.04sec)

隐式排序

对于隐式排序,我们可以参考Mysql官方的解释

大致解释一下:

GROUP BY 默认隐式排序(指在 GROUP BY 列没有 ASC 或 DESC 指示符的情况下也会进行排序)。然而,GROUP BY进行显式或隐式排序已经过时(deprecated)了,要生成给定的排序顺序,请提供 ORDER BY 子句。

所以,在Mysql8.0之前,Group by会默认根据作用字段(Group by的后接字段)对结果进行排序。在能利用索引的情况下,Group by不需要额外进行排序操作;但当无法利用索引排序时,Mysql优化器就不得不选择通过使用临时表然后再排序的方式来实现GROUP BY了。

且当结果集的大小超出系统设置临时表大小时,Mysql会将临时表数据copy到磁盘上面再进行操作,语句的执行效率会变得极低。这也是Mysql选择将此操作(隐式排序)弃用的原因。

基于上述原因,Mysql在8.0时,对此进行了优化更新:

大致解释一下:

从前(Mysql5.7版本之前),Group by会根据确定的条件进行隐式排序。在mysql 8.0中,已经移除了这个功能,所以不再需要通过添加order by null 来禁止隐式排序了,但是,查询结果可能与以前的 MySQL 版本不同。要生成给定顺序的结果,请按通过ORDER BY指定需要进行排序的字段。

因此,我们的结论也出来了:

在语义相同,有索引的情况下:

group by和distinct都能使用索引,效率相同。因为group by和distinct近乎等价,distinct可以被看做是特殊的group by。

在语义相同,无索引的情况下:

distinct效率高于group by。原因是distinct 和 group by都会进行分组操作,但group by在Mysql8.0之前会进行隐式排序,导致触发filesort,sql执行效率低下。

但从Mysql8.0开始,Mysql就删除了隐式排序,所以,此时在语义相同,无索引的情况下,group by和distinct的执行效率也是近乎等价的。

推荐group by的原因

group by语义更为清晰

group by可对数据进行更为复杂的一些处理

相比于distinct来说,group by的语义明确。且由于distinct关键字会对所有字段生效,在进行复合业务处理时,group by的使用灵活性更高,group by能根据分组情况,对数据进行更为复杂的处理,例如通过having对数据进行过滤,或通过聚合函数对数据进行运算。






审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • MySQL
    +关注

    关注

    1

    文章

    931

    浏览量

    29749
  • null
    +关注

    关注

    0

    文章

    19

    浏览量

    4337

原文标题:面试官:MySQL中的 distinct 和 group by 哪个效率更高?

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    相同性能与体积磁体:表磁为何不同?

    很多小伙伴可能都会有这样一个疑问,相同性能和体积的磁体,它们的表磁是一样的吗?表磁是指磁体表面某一特定点的磁感应强度。表磁是日常生活中较易直接测量的参数之一。相同性能和体积的磁体,表磁不一定一样
    的头像 发表于 04-14 09:04 356次阅读
    <b class='flag-5'>相同</b>性能与体积磁体:表磁为何不同?

    NCP5422A:双路异相同步降压控制器的深度解析与设计指南

    ,看看它有哪些独特之处,以及设计中需要注意的要点。 文件下载: NCP5422EVB.pdf 一、NCP5422A概述 NCP5422A是一款双N沟道同步降压调节器控制器,它集成了两个独立降压调节器所需的所有电路,采用(V^{2})控制方法,能够使用最少外部组件的
    的头像 发表于 04-11 16:40 693次阅读

    IRDCiP2005A - A 参考设计:高效双相同步降压转换器解析

    IRDCiP2005A - A 参考设计:高效双相同步降压转换器解析 电子设计领域,电源模块的高效性和稳定性至关重要。今天我们来详细探讨 International Rectifier
    的头像 发表于 03-29 09:40 155次阅读

    基于iP2001的4相同步降压转换器设计参考

    基于iP2001的4相同步降压转换器设计参考 电源设计领域,高效、稳定且易于设计的电源解决方案一直是工程师们追求的目标。今天,我们就来深入探讨一国际整流器(International
    的头像 发表于 03-29 09:30 136次阅读

    基于iP2001的2相同步降压转换器设计参考

    的IRDCiP2001 - A参考设计,为工程师们提供了一个基于iP2001的2相同步降压转换器解决方案,能够实验室环境轻松评估iP2001的性能,为实际项目设计提供了重要参考。 文件下载
    的头像 发表于 03-29 09:30 146次阅读

    电路板是否没有 tf 卡的情况下启动?

    电路板是否没有 tf 卡的情况下启动? 主板是否使用没有 tf 卡的 NVMe SSD 启动?
    发表于 03-26 07:14

    深入解析L6728单相同步降压控制器:特性、应用与设计要点

    深入解析L6728单相同步降压控制器:特性、应用与设计要点 电子设计领域,电源管理是一个至关重要的环节。今天,我们将深入探讨一款名为L6728的单相同步降压控制器,它在电源转换和管理方面具有出色
    的头像 发表于 03-24 16:15 135次阅读

    SGM62180:高效两相同步降压转换器的设计与应用

    SGM62180:高效两相同步降压转换器的设计与应用 电子设计领域,电源管理芯片的性能直接影响着整个系统的稳定性和效率。SGM62180作为一款高效的两相同步降压转换器,以其出色的性
    的头像 发表于 03-19 09:25 596次阅读

    LTC3784:高性能多相同步升压控制器的深度剖析

    LTC3784:高性能多相同步升压控制器的深度剖析 电子设计领域,电源管理芯片的性能直接影响着整个系统的稳定性和效率。LTC3784作为一款高性能的多相同步升压控制器,以其卓越的特性
    的头像 发表于 03-09 11:50 288次阅读

    MAX8791单相同步 MOSFET 驱动器:设计与应用详解

    MAX8791/MAX8791B 单相同步 MOSFET 驱动器:设计与应用详解 引言 现代电子设备中,高效的电源管理至关重要。对于笔记本电脑、台式机和服务器等设备的 CPU 核心电源供应,单相同
    的头像 发表于 02-04 15:20 241次阅读

    如何高效修改西门子PLC的相同IP地址

    IP 地址重复冲突的问题,无法实现数据采集与远程通信,将直接影响到设备联网率与信息化管理水平。 某企业多台PLC控制的设备在上网时出现相同IP冲突问题。由于设备较多,如果要求厂商工程师来到现场逐一修改IP的方式效率较低。一方面采取
    的头像 发表于 12-16 13:52 609次阅读
    如何高效修改西门子PLC的<b class='flag-5'>相同</b>IP地址

    为什么sconscript这么写,没有构建文件的情况下,反而会构建所有文件?

    在有一个文件夹有返回的时候,构建关系正常。 没有任何选择的情况下,构建关系异常。(这时候应该所有文件划伤×且不编译) 这是我sconscript的写法
    发表于 09-24 07:41

    CNC的IP地址相同冲突如何解决?

    在网络世界中,每个设备都需要一个独特的标识来确保信息的准确传输,这个标识就是IP地址。然而,CNC(数控机床)生产车间中,由于存在多个品牌、不同型号的设备,且这些设备在出厂测试时往往会被配备相同
    的头像 发表于 07-23 14:13 884次阅读
    CNC的IP地址<b class='flag-5'>相同</b>冲突如何解决?

    请问CYW20835sleep mode的情况下,不进入SDS或HIDOF的情况下,底电流最低是多少?

    请问CYW20835sleep mode的情况下,不进入SDS或HIDOF的情况下,底电流最低是多少?
    发表于 07-07 07:54

    国外PLC出现IP相同冲突如何解决

    设备是近期从不同供应商采购而来,部分设备在出厂时被预设了相同的默认IP地址,均为192.168.1.100。当这些PLC同时接入工厂网络时,网络系统立即报错,导致设备无法正常通信,整个监控系统陷入瘫痪状态,生产线也被迫暂停。 面对这一紧急情况
    的头像 发表于 05-15 17:05 1007次阅读
    国外PLC出现IP<b class='flag-5'>相同</b>冲突如何解决