group by与distinct效率分析及优化措施_DBTomato的博客-CSDN博客_tp6.0 distinct分组效率优化


本站和网页 https://blog.csdn.net/u013983450/article/details/52190699 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

group by与distinct效率分析及优化措施_DBTomato的博客-CSDN博客_tp6.0 distinct分组效率优化
group by与distinct效率分析及优化措施
DBTomato
于 2016-08-12 12:52:58 发布
72550
收藏
16
分类专栏:
SQL
文章标签:
mysql
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u013983450/article/details/52190699
版权
SQL
专栏收录该内容
2 篇文章
0 订阅
订阅专栏
如何使用group by进行去重
因为mysql的distinct在结果集中,全部不同,才可以去重。
所以,当我们进行去重处理的时候,需要单独对某列进行去重,可以使用group by子句进行分组去重
select _auto_id from account_login group by _auto_id; 该语句可以对_auto_id列进行去重。
在使用group by进行去重效率分析
无索引
0.23s
mysql> explain select _auto_id from account_login group by _auto_id;
+----+-------------+---------------+------+---------------+------+---------+------+--------+---------------------------------+
| id | select_type | table         | type | possible_keys | key  | key_len | ref  | rows   | Extra                           |
+----+-------------+---------------+------+---------------+------+---------+------+--------+---------------------------------+
|  1 | SIMPLE      | account_login | ALL  | NULL          | NULL | NULL    | NULL | 133257 | Using temporary; Using filesort |
+----+-------------+---------------+------+---------------+------+---------+------+--------+---------------------------------+
mysql> show profile;
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000154 |
| checking permissions | 0.000012 |
| Opening tables       | 0.000029 |
| init                 | 0.000029 |
| System lock          | 0.000014 |
| optimizing           | 0.000010 |
| statistics           | 0.000021 |
| preparing            | 0.000020 |
| Creating tmp table   | 0.000036 |
| Sorting result       | 0.000007 |
| executing            | 0.000005 |
| Sending data         | 0.207841 |
| Creating sort index  | 0.021024 |
| end                  | 0.000010 |
| removing tmp table   | 0.000130 |
| end                  | 0.000010 |
| query end            | 0.000016 |
| closing tables       | 0.000019 |
| freeing items        | 0.000035 |
| cleaning up          | 0.000039 |
+----------------------+----------+
20 rows in set, 1 warning (0.00 sec)
此处创建了sort index进行排序,说明对MySQL使用了内存临时表,
group by后面的排序过程是使用sort index来完成的,而且该内存临时表的大小是由MAX_HEAP_TABLE_SIZE来控制。
Sending data 显示的这个时间 = Time(Sending data) + Time (Sorting result), 这样其实应该是排序所用的时间
因为在group by后会进行自动排序,如果该我们仅仅想去重,而不需要排序,可以使用
mysql> explain select _auto_id from account_login group by _auto_id order by null;
+----+-------------+---------------+------+---------------+------+---------+------+--------+-----------------+
| id | select_type | table         | type | possible_keys | key  | key_len | ref  | rows   | Extra           |
+----+-------------+---------------+------+---------------+------+---------+------+--------+-----------------+
|  1 | SIMPLE      | account_login | ALL  | NULL          | NULL | NULL    | NULL | 133257 | Using temporary |
+----+-------------+---------------+------+---------------+------+---------+------+--------+-----------------+
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000155 |
| checking permissions | 0.000012 |
| Opening tables       | 0.000029 |
| init                 | 0.000029 |
| System lock          | 0.000014 |
| optimizing           | 0.000009 |
| statistics           | 0.000022 |
| preparing            | 0.000020 |
| Creating tmp table   | 0.000042 |
| executing            | 0.000006 |
| Sending data         | 0.219640 |
| end                  | 0.000021 |
| removing tmp table   | 0.000014 |
| end                  | 0.000008 |
| query end            | 0.000014 |
| closing tables       | 0.000020 |
| freeing items        | 0.000033 |
| cleaning up          | 0.000020 |
+----------------------+----------+
可以发现,在加入order by null子句后,MySQL并没有创建sort index进行排序(内存排序非常快,优化效果并不明显,并且这个阶段只是每个数据块的排序,)。但是在group by后添加多列,并且不能进行
有索引
mysql> explain select _auto_id from account_login group by _auto_id;
使用时间 0.11s
执行计划
+----+-------------+---------------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table         | type  | possible_keys | key     | key_len | ref  | rows   | Extra       |
+----+-------------+---------------+-------+---------------+---------+---------+------+--------+-------------+
|  1 | SIMPLE      | account_login | index | idx_acc       | idx_acc | 4       | NULL | 133257 | Using index |
+----+-------------+---------------+-------+---------------+---------+---------+------+--------+-------------+
profile
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000140 |
| checking permissions | 0.000011 |
| Opening tables       | 0.000027 |
| init                 | 0.000028 |
| System lock          | 0.000014 |
| optimizing           | 0.000009 |
| statistics           | 0.000035 |
| preparing            | 0.000028 |
| Sorting result       | 0.000006 |
| executing            | 0.000005 |
| Sending data         | 0.105595 |
| end                  | 0.000012 |
| query end            | 0.000013 |
| closing tables       | 0.000015 |
| freeing items        | 0.000026 |
| cleaning up          | 0.000034 |
+----------------------+----------+
explain select _auto_id from account_login group by _auto_id   时间0.11s
explain select _auto_id from account_login group by _auto_id order by null  时间0.11s
在使用索情况下,因为使用了索引自身的有序性,所以不需MySQL再次创建临时表(create sort index)进行排序,可以直接输出有序结果,两者的计算时间相同。
正常使用场景效率分析
mysql> explain select _auto_id,max(date) from account_login group by _auto_id;
没有索引
用时 3.16s
+----+-------------+---------------+------+---------------+------+---------+------+--------+---------------------------------+
| id | select_type | table         | type | possible_keys | key  | key_len | ref  | rows   | Extra                           |
+----+-------------+---------------+------+---------------+------+---------+------+--------+---------------------------------+
|  1 | SIMPLE      | account_login | ALL  | NULL          | NULL | NULL    | NULL | 133257 | Using temporary; Using filesort |
+----+-------------+---------------+------+---------------+------+---------+------+--------+---------------------------------+
mysql> show profile;
+---------------------------+----------+
| Status                    | Duration |
+---------------------------+----------+
| starting                  | 0.000111 |
| checking permissions      | 0.000010 |
| Opening tables            | 0.000018 |
| init                      | 0.000030 |
| System lock               | 0.000011 |
| optimizing                | 0.000007 |
| statistics                | 0.000014 |
| preparing                 | 0.000013 |
| Creating tmp table        | 0.000037 |
| Sorting result            | 0.000007 |
| executing                 | 0.000005 |
| Sending data              | 0.545211 |
| converting HEAP to MyISAM | 1.307225 |
| Sending data              | 0.738511 |
| Creating sort index       | 0.573640 |
| end                       | 0.000020 |
| removing tmp table        | 0.001682 |
| end                       | 0.000009 |
| query end                 | 0.000012 |
| closing tables            | 0.000016 |
| freeing items             | 0.000030 |
| logging slow query        | 0.000051 |
| cleaning up               | 0.000018 |
+---------------------------+----------+
在group by过程中,先使用sort index对group by子句进行处理,然后创建临时表,然后转换到磁盘临时表使用文件排序取出max(date)
如果group by后面列数过多(即使不排序),也是会用converting HEAP to MyISAM
converting HEAP to MyISAM 该语句表明了在执行过程中,内存临时表转变成了硬盘临时表。可以使用 tmp_table_size,MAX_HEAP_TABLE_SIZE来改变内存临时表的最大大小,但是在该SQL下,因为要使用文件排序,所以无论内存临时表设置多大,都会进行内存临时表到文件临时表的转变。
有索引情况
时间 0.31s
mysql>  explain select _auto_id,max(date) from account_login group by _auto_id;
+----+-------------+---------------+-------+---------------+---------+---------+------+--------+-------+
| id | select_type | table         | type  | possible_keys | key     | key_len | ref  | rows   | Extra |
+----+-------------+---------------+-------+---------------+---------+---------+------+--------+-------+
|  1 | SIMPLE      | account_login | index | idx_acc       | idx_acc | 4       | NULL | 133257 | NULL  |
+----+-------------+---------------+-------+---------------+---------+---------+------+--------+-------+
profile
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000109 |
| checking permissions | 0.000010 |
| Opening tables       | 0.000022 |
| init                 | 0.000031 |
| System lock          | 0.000012 |
| optimizing           | 0.000007 |
| statistics           | 0.000021 |
| preparing            | 0.000022 |
| Sorting result       | 0.000006 |
| executing            | 0.000005 |
| Sending data         | 0.314817 |
| end                  | 0.000024 |
| query end            | 0.000015 |
| closing tables       | 0.000032 |
| freeing items        | 0.000042 |
| cleaning up          | 0.000023 |
+----------------------+----------+
在有索引的情况下,仅仅靠索引本身就完成了全部需求。
distinct进行分析
 explain select distinct(_auto_id) from account_login;
+----+-------------+---------------+------+---------------+------+---------+------+--------+-----------------+
| id | select_type | table         | type | possible_keys | key  | key_len | ref  | rows   | Extra           |
+----+-------------+---------------+------+---------------+------+---------+------+--------+-----------------+
|  1 | SIMPLE      | account_login | ALL  | NULL          | NULL | NULL    | NULL | 133257 | Using temporary |
+----+-------------+---------------+------+---------------+------+---------+------+--------+-----------------+
mysql> show profile;
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000087 |
| checking permissions | 0.000009 |
| Opening tables       | 0.000016 |
| init                 | 0.000016 |
| System lock          | 0.000011 |
| optimizing           | 0.000007 |
| statistics           | 0.000013 |
| preparing            | 0.000014 |
| Creating tmp table   | 0.000026 |
| executing            | 0.000006 |
| Sending data         | 0.221214 |
| end                  | 0.000024 |
| removing tmp table   | 0.000190 |
| end                  | 0.000011 |
| query end            | 0.000014 |
| closing tables       | 0.000019 |
| freeing items        | 0.000036 |
| cleaning up          | 0.000024 |
+----------------------+----------+
select distinct _auto_id,sid,uid from account_login;
+---------------------------+----------+
| Status                    | Duration |
+---------------------------+----------+
| starting                  | 0.000095 |
| checking permissions      | 0.000010 |
| Opening tables            | 0.000019 |
| init                      | 0.000019 |
| System lock               | 0.000010 |
| optimizing                | 0.000006 |
| statistics                | 0.000015 |
| preparing                 | 0.000016 |
| Creating tmp table        | 0.000030 |
| executing                 | 0.000006 |
| Sending data              | 0.529466 |
| converting HEAP to MyISAM | 1.928813 |
| Sending data              | 0.157253 |
| end                       | 0.000020 |
| removing tmp table        | 0.002778 |
| end                       | 0.000009 |
| query end                 | 0.000012 |
| closing tables            | 0.000016 |
| freeing items             | 0.000031 |
| logging slow query        | 0.000062 |
| cleaning up               | 0.000033 |
+---------------------------+----------+
发现distinct和没有排序的group by几乎是一样的,并且在进行多列的去重的时候也使用了 converting HEAP to MyISAM进行汇总
总结:
create sort index 使用内存临时表进行分块排序,分块排序后再进入磁盘进行汇总排序
converting HEAP to MyISAM 是进入硬盘进行汇总排序,如果group by数据列过多,即使不排序,也需要使用磁盘临时表进行汇总数据。
group by的主要消耗是在临时表排序阶段,而不是分组阶段。
所以制约group by性能的问题,就是临时表+排序,尽量减少磁盘排序,较少磁盘临时表的创建,是比较有用的处理办法。
最好的办法就是在group by条件后,添加索引或者复合索引,这样MySQL就会利用索引完成排序,分组
                                                                                                                                                                                                                                  By DBTomato
DBTomato
关注
关注
点赞
16
收藏
打赏
评论
group by与distinct效率分析及优化措施
如何使用group by进行去重因为mysql的distinct在结果集中,全部不同,才可以去重。所以,当我们进行去重处理的时候,需要单独对某列进行去重,可以使用group by子句进行分组去重select _auto_id from account_login group by _auto_id; 该语句可以对_auto_id列进行去重。在使用group
复制链接
扫一扫
专栏目录
MySQL中distinct与group by之间的性能进行比较
09-10
主要针对MySQL中distinct与group by之间的性能进行比较,内容比较详细,很直观的能看出比较结果,感兴趣的小伙伴们可以参考一下
去重是distinct还是group by?
热门推荐
梁吉林的博客
04-24
10万+
distinct简单来说就是用来去重的,而group by的设计目的则是用来聚合统计的,两者在能够实现的功能上有些相同之处,但应该仔细区分,因为用错场景的话,效率相差可以倍计。单纯的去重操作使用distinct,速度是快于group by的。distinctdistinct支持单列、多列的去重方式。
单列去重的方式简明易懂,即相同值只保留1个。
多列的去重则是根据指定的去重的列信息来进行,即只有
评论 4
您还未登录,请先
登录
后发表或查看评论
MySQL去重中 distinct 和 group by 的区别
最新发布
xiaoheihai666的博客
11-04
2719
今天在写业务需要对数据库重复字段进行去重时,因为是去重,首先想到的是distinct关键字。于是我在distinct后面加上了id,distinct查出来的数据就是全部数据了,相当于distinct没起作用。而 group by 可以针对要查询的全部字段中的部分字段去重,它的作用主要是:获取数据表中以分组字段为依据的其他统计数据。distinct适合查单个字段去重,支持单列、多列的去重方式。即只有所有指定的列信息都相同,才会被认为是重复的信息。多列的去重则是根据指定的去重的列信息来进行,
Sql优化(二) 快速计算Distinct Count
技术世界
03-28
883
原创文章,始发自本人个人博客站点,转载请务必注明出自http://www.jasongj.com
个人博客上本文链接http://www.jasongj.com/2015/03/15/count_distinct/
UV vs. PV
  在互联网中,经常需要计算UV和PV。所谓PV即Page View,网页被打开多少次(YouTube等视频网站非常重视视频的点击率,即被播放多...
Oracle——distinct的用法(效率)
haiross的专栏
12-31
1万+
Oracle——distinct的用法
博客分类:
Oracle
oracledistinctgroup
by
distinct这个关键字来过滤掉多余的重复记录只保留一条,但往往只用 它来返回不重复记录的条数,而不是用它来返回不重记录的所有值。其原因是distinct只有用二重循环查询来解决,而这样对于一个数据量非常大的站来说,无疑是会直接影响到效率
mysql distinct 慢_分析MySQL中优化distinct的技巧
lz610756247的专栏
12-31
1877
有这样的一个需求:select count(distinct nick) from user_access_xx_xx;
这条sql用于统计用户访问的uv,由于单表的数据量在10G以上,即使在user_access_xx_xx上加上nick的索引,
通过查看执行计划,也为全索引扫描,sql在执行的时候,会对整个服务器带来抖动;
root@db 09:00:12>select count(distinct nick) from user_access;
+———————-+
| count(d
使用group by 去重
斯特凡今天也很帅的博客
06-16
2029
distinct去重
select count(distinct(column1))
from 表名
where column3=20210611;
group by去重
select
column1,
count(1)
from
表名
where
column3=20210611
group by
column1;
groupby去重
weixin_40718824的博客
03-18
5237
Groupby 分组后,如果没有对分组后的数据进行操作,如对每组求和 取平均 取最小等操作,分组后直接显示,则默认显示
该分组的第一条数据。
第一幅图是没有进行groupby操作后的数据,数据共有48条
下图是在第一幅的基础上按照s_id进行groupby的操作,可以看出只显示按照s_id分组后每组的第一条数据
下图是在第一幅的基础上对s_id,c_id进行分组的每组的第一条数据,在第一副中,前三条为第一组,4-6条为第二组,每组
中s_id,c_id都是相同的。
...
distinct效率更高还是group by效率更高?
猾枭的博客
06-29
9159
原创文章,希望多多关注支持,感谢。
目录
00 结论
01 distinct的使用
02 group by的使用
03 distinct和group by原理 *
04 推荐group by的原因
00结论
先说大致的结论(完整结论在文末):
在语义相同,有索引的情况下
group by和distinct都能使用索引,效率相同。
在语义相同,无索引的情况下:
distinct效率高于group by。原因是distinct 和 group by都会进行分组操作,但group by可能会进行排序,触发fil
group by 去重处理数据
qq_38807606的博客
03-22
1739
1.
# 需求:结果:
# + ----+------+
# | name|boy_id|
# + ----+------+
# | A |1 |
# | B |2 |
# | C |3 |
# + ----+------+
# group by 对结果的重复数据去重
select * from girl ;
# +--+----+------+
# |id|name|boy_id|
# +--+----+------+
# |1 |A |1
distinct和group by的效率比较
奋斗的阿杰的博客
07-25
1512
distinct和group by的性能比较
count(distinct())效率优化
eagle89的专栏
09-16
1万+
如何提升自身sql效率,更快得到想要的数据,是每一个使用sql的同学都需要学习和关注的事情。
sql作为面向大众的数据提取工具,除了研发、数据分析师,产品经理及业务运营同学也都有应用需求。只要sql无语法错误,保持等待,或长或短都是可以输出结果的。但是在数据量庞大或数据逻辑复杂时,或碰上线上资源紧张,或者好不容易等了3小时、结果发现数据有点异常需要修改后重跑,不知道有没有同学有相同的经历。
低效是每位同学都不乐见的,而避免这个问题就要求我们学习优化sql的方法,从而减少自己等数的焦虑时光。
而其中最常
mysql groupBy和distinct区别,以及性能差异
仅做个人笔记
11-25
3940
转自:
https://blog.csdn.net/qdqht2009/article/details/79202799
https://blog.csdn.net/qq_33314107/article/details/80424155
仅做个人笔记,浏览请看原贴
groupBy和distinct区别
在使用MySQL时,有时需要查询出某个字段不重复的记录,这时可以使用mysql...
mysql count distinct太慢_MySQL COUNT(*)和DISTINCT效率分析
weixin_35681614的博客
01-21
519
MySQL数据库对于COUNT(*)的不同处理会造成不同的结果,比如,执行下面查询时,即使对于千万级别的数据mysql也能非常迅速的返回结果。SELECTCOUNT(*) FROM tablename但如果这样执行,mysql的查询时间开始攀升。SELECT COUNT(*) FROM tablename WHERE…..当没有WHERE语句对于整个mysql的表进行count运算的时候,M...
group by 和 distinct 效率对比
foralllove的博客
05-16
771
数据库
CREATE TABLE `tb_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_name` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`user_password` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`birth` datetime DEFAULT NULL,
`sex` c...
MySQL 5.7 下 distinct 和 group by 效率性能比较
sleepybear1113的博客
04-29
2460
MySQL 5.7 下 distinct 和 group by 效率性能比较前言环境数据表结构测试开始测试范围测试 1(不使用 where)测试 2(使用 where 语句,id < 100000)测试 3(使用 where 语句,id < 500000)测试 4(使用 where 语句,id < 1000000)测试 5(使用 where 语句,1586448000000 &l...
group by 分组去重
小哇
09-21
4630
SELECT a.projectname,a.code,a.statename,a.managerid,a.managername FROM pms_project AS a
INNER JOIN
SELECT CODE,MAX(managerid) AS managerid FROM pms_project
GROUP BY CODE
) AS t
ON a.managerid=t.ma...
oracle distict 效率,为什么用distinct时很慢?解决方法
weixin_39684995的博客
04-12
1575
当前位置:我的异常网» Oracle管理»为什么用distinct时很慢?解决方法为什么用distinct时很慢?解决方法www.myexceptions.net网友分享于:2013-05-09浏览:451次为什么用distinct时很慢?为什么用distinct时很慢?以下select语句很快就得到结果,共有十几万行,但是有很多重复行,selectJ030.* from(select...
distinct和group by区别
qq_33380252的博客
11-23
2万+
关于去重作用(转载地址:https://blog.csdn.net/ljl890705/article/details/70602442)
distinct简单来说就是用来去重的,而group by的设计目的则是用来聚合统计的,两者在能够实现的功能上有些相同之处,但应该仔细区分,因为用错场景的话,效率相差可以倍计。
单纯的去重操作使用distinct,速度是快于group by的。
dist...
“相关推荐”对你有帮助么?
非常没帮助
没帮助
一般
有帮助
非常有帮助
提交
©️2022 CSDN
皮肤主题:大白
设计师:CSDN官方博客
返回首页
DBTomato
CSDN认证博客专家
CSDN认证企业博客
码龄9年
暂无认证
15
原创
21万+
周排名
182万+
总排名
13万+
访问
等级
820
积分
粉丝
15
获赞
评论
30
收藏
私信
关注
热门文章
group by与distinct效率分析及优化措施
72550
Scala处理JSON
20265
mysqldump --single-transaction 和--lock-tables参数详解
11767
ES基础操作
11127
利用MySQL的表实现树的构建以及优化
6564
分类专栏
MySQL
2篇
Hive
Hadoop
Java
2篇
Scala
1篇
Linux
Oracle
Spark
Python
3篇
Redis
SQL
2篇
数据结构
1篇
算法
架构
Kafka
1篇
Elasticsearch
1篇
最新评论
group by与distinct效率分析及优化措施
悟空他二师弟
回复
姚一号: 是的呀,distinct 只针对结果集全部去重。
group by与distinct效率分析及优化措施
weixin_43818962:
有索引,用那种方式去重?
group by与distinct效率分析及优化措施
盼超师兄:
test
JAVA常用的JSON处理库,常用处理方法
木小板:
讲得很不错,我这里正好也分享一点jackson处理json的一些基础经验,大家一起交流交流。http://edu.51cto.com/course/15120.html
group by与distinct效率分析及优化措施
姚一号:
"distinct在结果集中,全部不同,才可以去重",你确定是这样的???
您愿意向朋友推荐“博客详情页”吗?
强烈不推荐
不推荐
一般般
推荐
强烈推荐
提交
最新文章
python数据分析---Numpy
python数据分析---Pandas
MySQL统计信息
2017年2篇
2016年14篇
目录
目录
分类专栏
MySQL
2篇
Hive
Hadoop
Java
2篇
Scala
1篇
Linux
Oracle
Spark
Python
3篇
Redis
SQL
2篇
数据结构
1篇
算法
架构
Kafka
1篇
Elasticsearch
1篇
目录
评论 4
被折叠的 条评论
为什么被折叠?
到【灌水乐园】发言
查看更多评论
打赏作者
DBTomato
你的鼓励将是我创作的最大动力
¥2
¥4
¥6
¥10
¥20
输入1-500的整数
余额支付
(余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付
您的余额不足,请更换扫码支付或充值
打赏作者
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额
抵扣说明:
1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。
余额充值