MySQL 中的 distinct 和 group by 哪个效率更高?

1 篇文章 0 订阅
订阅专栏

先说大致的结论(完整结论在文末):

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

基于这个结论,你可能会问:为什么在语义相同,有索引的情况下,group by和distinct效率相同?且在什么情况下,group by会进行排序操作?带着这两个问题找答案。接下来,我们先来看一下distinct和group by的基础使用。 

 

 

 distinct的使用

                                      distinct用法

SELECT DISTINCT columns FROM table_name WHERE where_conditions;

例如:

mysql> select distinct age from student;+------+| age  |+------+|   10 ||   12 ||   11 || NULL |+--

DISTINCT 关键词用于返回唯一不同的值。放在查询语句中的第一个字段前使用,且「作用于主句所有列」。如果列具有NULL值,并且对该列使用DISTINCT子句,MySQL将保留一个NULL值,并删除其它的NULL值,因为DISTINCT子句将所有NULL值视为相同的值 

 

                                                             distinct多列去重

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

SELECT DISTINCT column1,column2 FROM table_name WHERE where_conditions;
mysql> select distinct sex,age from student;+--------+------+| sex    | age  |+--------+------+| male   |   10 || female |   12 || male   |   11 || male   | NULL || female |   11 |+--------+------+5 rows in set (0.02 sec)

group by的使用

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

                                                        单列去重

 

语法:

SELECT columns FROM table_name WHERE where_conditions GROUP BY columns;

执行:

mysql> select age from student group by age;+------+| age  |+------+|   10 ||   12 ||   11 || NULL |+

 

                                                            多列去重

语法:

SELECT columns FROM table_name WHERE where_conditions GROUP BY columns;

执行:

mysql> select sex,age from student group by sex,age;+--------+------+| sex    | age  |+--------+------+| male   |   10 || female |   12 || male   |   11 || male   | NULL || female |   11 |+--------+------+5 rows in set (0.03 sec)

                                                            区别示例

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

mysql> select sex,age from student group by sex;+--------+-----+| sex    | age |+--------+-----+| male   |  10 || female |  12 |+--------+-----+2 rows in set (0.03 sec)

distinct和group by原理

在大多数例子中,DISTINCT可以被看作是特殊的GROUP BY,它们的实现都基于分组操作,且都可以通过「松散索引扫描、紧凑索引扫描」(关于索引扫描的内容会在其他文章中详细介绍,就不在此细致介绍了)来实现。DISTINCT和GROUP BY都是「可以使用索引进行扫描搜索」的。例如以下两条sql(只单单看表格最后extra的内容),我们对这两条sql进行分析,可以看到,在extra中,这两条sql都使用了紧凑索引扫描Using index for group-by。所以,在一般情况下,对于相同语义的DISTINCT和GROUP BY语句,我们可以对其使用相同的索引优化手段来进行优化。

mysql> explain select int1_index from test_distinct_groupby group by int1_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 | Using index for group-by |+----+-------------+-----------------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+1 row in set (0.05 sec)mysql> explain select distinct int1_index from test_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 | Using index for group-by |+----+-------------+-----------------------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+1 row in set (0.05 sec)

但对于GROUP BY来说,在MYSQL8.0之前,GROUP Y默认会依据字段进行「隐式排序」。可以看到,下面这条sql语句在使用了临时表的同时,还进行了filesort。

mysql> explain select int6_bigger_random from test_distinct_groupby GROUP BY int6_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 | Using temporary; Using filesort |+----+-------------+-----------------------+------------+------+---------------+------+---------+------+-------+----------+---------------------------------+1 row in set (0.04 sec)

 

                                                            隐式排序

对于隐式排序,我们可以参考Mysql官方的解释:MySQL :: MySQL 5.7 Reference Manual :: 8.2.1.14 ORDER BY Optimization

GROUP BY implicitly sorts by default (that is, in the absence of ASC or DESC designators for GROUP BY columns). However, relying on implicit GROUP BY sorting (that is, sorting in the absence of ASC or DESC designators) or explicit sorting for GROUP BY (that is, by using explicit ASC or DESC designators for GROUP BY columns) is deprecated. To produce a given sort order, provide an ORDER BY clause.

大致解释一下:

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时,对此进行了优化更新:MySQL :: MySQL 8.0 Reference Manual :: 8.2.1.16 ORDER BY Optimization

Previously (MySQL 5.7 and lower), GROUP BY sorted implicitly under certain conditions. In MySQL 8.0, that no longer occurs, so specifying ORDER BY NULL at the end to suppress implicit sorting (as was done previously) is no longer necessary. However, query results may differ from previous MySQL versions. To produce a given sort order, provide an ORDER BY clause.

大致解释一下:

从前(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的原因

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

 

 

面试官:MySQL distinctgroup by 哪个效率更高
m0_71777195的博客
07-02 140
DISTINCTGROUP BY都是可以使用索引进行扫描搜索的。例如以下两条sql(只单单看表格最后extra的内容),我们对这两条sql进行分析,可以看到,在extra,这两条sql都使用了紧凑索引扫描。所以,在一般情况下,对于相同语义的DISTINCTGROUP BY语句,我们可以对其使用相同的索引优化手段来进行优化。但对于GROUP BY来说,在MYSQL8.0之前,GROUP Y默认会依据字段进行隐式排序。可以看到,下面这条sql语句在使用了临时表的同时,还进行了filesort。
SQL语句去重是用distinct还是用group by呢?
沙漠渔溏
05-18 635
distinct简单来说就是用来去重的 group by的设计目的则是用来聚合统计的 两者在能够实现的功能上有些相同之处,但应该仔细区分,因为用错场景的话,效率相差可以倍计。 单纯的去重操作使用distinct,速度是快于group by的。 distinct支持单列、多列的去重方式。 单列去重的方式简明易懂,即相同值只保留1个。 多列的去重则是根据指定的去重的列信息来进行,即只有所有指定的列信息都相同,才会被认为是重复的信息 干巴巴的说不好理解,示例一下: 示例数据表的数据: mysql> sel
MySQL distinctgroup by 哪个效率更高
最新发布
shi19950304的博客
08-01 755
为什么在语义相同,有索引的情况下,group by和distinct效率相同? 在什么情况下,group by会进行排序操作? 带着这两个问题找答案。接下来,我们先来看一下distinctgroup by的基础使用。
去重是distinct还是group by?
热门推荐
梁吉林的博客
04-24 10万+
distinct简单来说就是用来去重的,而group by的设计目的则是用来聚合统计的,两者在能够实现的功能上有些相同之处,但应该仔细区分,因为用错场景的话,效率相差可以倍计。单纯的去重操作使用distinct,速度是快于group by的。distinctdistinct支持单列、多列的去重方式。 单列去重的方式简明易懂,即相同值只保留1个。 多列的去重则是根据指定的去重的列信息来进行,即只有
关于distinctgroup by的去重逻辑浅析
liuzhiqiangruc
03-22 2869
数据库操作,我们常常遇到需要将数据去重计数的工作。例如: 表A,列col A C A B C D A B   结果就是一共出现4个不同的字母A、B、C、D 即结果为4 大体上我们可以选择count(distinct col)的方法和group+count的方法。 分别为: select count(distinct col) from A; select co...
distinct效率更高还是group by效率更高
猾枭的博客
06-29 1万+
原创文章,希望多多关注支持,感谢。 目录 00 结论 01 distinct的使用 02 group by的使用 03 distinctgroup by原理 * 04 推荐group by的原因 00结论 先说大致的结论(完整结论在文末): 在语义相同,有索引的情况下 group by和distinct都能使用索引,效率相同。 在语义相同,无索引的情况下: distinct效率高于group by。原因是distinctgroup by都会进行分组操作,但group by可能会进行排序,触发fil
MySQLdistinctgroup by 哪个效率更高
m0_71777195的博客
03-18 449
先说大致的结论:group by和distinct都能使用索引,效率相同。distinct效率高于group by。原因是distinctgroup by都会进行分组操作,但group by可能会进行排序,触发filesort,导致sql执行效率低下。基于这个结论,你可能会问:为什么在语义相同,有索引的情况下,group by和distinct效率相同?在什么情况下,group by会进行排序操作?带着这两个问题找答案,接下来我们先来看一下distinctgroup by的基础使用。
MySQLdistinctgroup by之间的性能进行比较
09-10
主要针对MySQLdistinctgroup by之间的性能进行比较,内容比较详细,很直观的能看出比较结果,感兴趣的小伙伴们可以参考一下
distinctgroup by 谁的效率高?
心似海
01-26 1541
最好需要哪个的时候用哪个,group by是用来分组统计的,能用disitnct的地方就不要用group by 了。
面试官:MySQLdistinctgroup by哪个效率更高
Java精选
12-22 475
结论先说大致的结论(完整结论在文末):在语义相同,有索引的情况下:group by和distinct都能使用索引,效率相同。在语义相同,无索引的情况下:distinct效率高于group by。原因是distinctgroup by都会进行分组操作,但group by可能会进行排序,触发filesort,导致sql执行效率低下。基于这个结论,你可能会问:为什么在语义相同,有索引的情况下,gr...
写文章

热门文章

  • java调用http接口的几种方式总结 17174
  • PL/SQL登录Oracle数据库报错ORA-12154:TNS:无法解析指定的连接标识符已解决(本地未安装Oracle需要连接服务器上的) 16814
  • python实现十大经典算法 14402
  • eclipse 删除的项目怎么恢复 12471
  • java获取当前时间和前一天日期 9409

分类专栏

  • 11 23篇
  • java 5篇
  • windows设置 2篇
  • 数据库 4篇
  • 人脸识别 1篇
  • jdk1.8 7篇
  • spring 4篇
  • springboot 2篇
  • datagrip 2篇
  • nginx 1篇
  • mybatis 2篇
  • mysql 1篇
  • plsql 1篇
  • python 1篇
  • NC 21篇
  • ecplise 8篇
  • NCC 5篇
  • 端口占用 1篇
  • 解析 7篇
  • 前端 2篇
  • js 2篇

最新评论

  • Win11家庭版找不到gpedit.msc文件怎么办?

    Long_Dragon_v: 第二个方法成功了

  • 拦截器是基于反射还是动态代理来实现的?

    java架构师uuid(): 基于过滤器链和处理器链实现的,你说的函数回调那是doFilter的实现。

  • Win11家庭版找不到gpedit.msc文件怎么办?

    2401_86340126: 三个方法都没用咋办表情包

  • 人脸识别-Java实现刷脸登录

    qq_49952257: 有原文链接吗

  • 拦截器是基于反射还是动态代理来实现的?

    righting1: 动态代理应该也用到了反射吧

大家在看

  • C++ | Leetcode C++题解之第429题N叉树的层序遍历 128
  • PHP isset() 和 empty() 区别
  • PHP中如何使用三元条件运算符
  • C++ | Leetcode C++题解之第430题扁平化多级双向链表
  • Golang | Leetcode Golang题解之第429题N叉树的层序遍历

最新文章

  • Java生成exe可执行文件
  • 对比2个对象属性的差异
  • Windows Update禁用后自动开启的解决办法
2023年27篇
2022年30篇
2021年12篇
2020年29篇
2019年13篇
2018年20篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家深圳多边形玻璃钢花盆浙江室内商场美陈批发河北玻璃钢雕塑摆件研究金昌玻璃钢景观雕塑定做气球商场美陈哪家值得信赖伊春人物玻璃钢雕塑定做党建文化玻璃钢雕塑有哪些临夏玻璃钢雕塑制作厂家商场美陈欣赏四川商场美陈生产厂家四川玻璃钢花盆制造江汉商场美陈品牌企业商场美陈服装展台创意武汉步行街玻璃钢雕塑定做价格吉林特色玻璃钢雕塑方法辽宁大型商场创意商业美陈制作玻璃钢公园雕塑看河南欧式玻璃钢雕塑生产厂家台州玻璃钢陶瓷雕塑介绍玻璃钢雕塑国内外研究现状室内不锈钢玻璃钢人物雕塑公司甘南广场玻璃钢雕塑多少钱红色玻璃钢卡通雕塑哪里买西安玻璃钢雕塑定价潍坊卡通玻璃钢雕塑厂家中山玻璃钢雕塑价格表淮南学校玻璃钢雕塑市场江西创意玻璃钢雕塑设计安徽主题公园玻璃钢雕塑艺术小品抚州景观玻璃钢雕塑供应商香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化