91网首页-91网页版-91网在线观看-91网站免费观看-91网站永久视频-91网站在线播放

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

MySQL 中的 distinct 和 group by 哪個(gè)效率更高?

admin
2023年3月6日 16:33 本文熱度 1154
先說大致的結(jié)論(完整結(jié)論在文末):
  • 在語義相同,有索引的情況下:group by和distinct都能使用索引,效率相同。
  • 在語義相同,無索引的情況下:distinct效率高于group by。原因是distinct 和 group by都會(huì)進(jìn)行分組操作,但group by可能會(huì)進(jìn)行排序,觸發(fā)filesort,導(dǎo)致sql執(zhí)行效率低下。

基于這個(gè)結(jié)論,你可能會(huì)問:

  • 為什么在語義相同,有索引的情況下,group by和distinct效率相同?
  • 在什么情況下,group by會(huì)進(jìn)行排序操作?

帶著這兩個(gè)問題找答案。接下來,我們先來看一下distinct和group by的基礎(chǔ)使用。

distinct的使用

distinct用法
select DISTINCT columns from table_name where where_conditions;

例如:

mysql> select distinct age from student;
+------+
| age  |
+------+
|   10 |
|   12 |
|   11 |
| NULL |
+------+
4 rows in set (0.01 sec)

DISTINCT 關(guān)鍵詞用于返回唯一不同的值。放在查詢語句中的第一個(gè)字段前使用,且作用于主句所有列。

如果列具有NULL值,并且對(duì)該列使用DISTINCT子句,MySQL將保留一個(gè)NULL值,并刪除其它的NULL值,因?yàn)?code style="margin: 0px 2px; padding: 2px 4px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; border-radius: 4px; background-color: rgba(27, 31, 35, 0.05); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(255, 93, 108);">DISTINCT子句將所有NULL值視為相同的值。

distinct多列去重

distinct多列的去重,則是根據(jù)指定的去重的列信息來進(jìn)行,即只有所有指定的列信息都相同,才會(huì)被認(rèn)為是重復(fù)的信息。

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的使用

對(duì)于基礎(chǔ)去重來說,group by的使用和distinct類似:

單列去重

語法:

select columns from table_name where where_conditions GROUP BY columns;

執(zhí)行:

mysql> select age from student group by age;
+------+
| age  |
+------+
|   10 |
|   12 |
|   11 |
| NULL |
+------+
4 rows in set (0.02 sec)
多列去重

語法:

select columns from table_name where where_conditions GROUP BY columns;

執(zhí)行:

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)
區(qū)別示例

兩者的語法區(qū)別在于,group by可以進(jìn)行單列去重,group by的原理是先對(duì)結(jié)果進(jìn)行分組排序,然后返回每組中的第一條數(shù)據(jù)。且是根據(jù)group by的后接字段進(jìn)行去重的。

例如:

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原理

在大多數(shù)例子中,DISTINCT可以被看作是特殊的GROUP BY,它們的實(shí)現(xiàn)都基于分組操作,且都可以通過松散索引掃描、緊湊索引掃描(關(guān)于索引掃描的內(nèi)容會(huì)在其他文章中詳細(xì)介紹,就不在此細(xì)致介紹了)來實(shí)現(xiàn)。

DISTINCTGROUP BY都是可以使用索引進(jìn)行掃描搜索的。例如以下兩條sql(只單單看表格最后extra的內(nèi)容),我們對(duì)這兩條sql進(jìn)行分析,可以看到,在extra中,這兩條sql都使用了緊湊索引掃描Using index for group-by

所以,在一般情況下,對(duì)于相同語義的DISTINCTGROUP BY語句,我們可以對(duì)其使用相同的索引優(yōu)化手段來進(jìn)行優(yōu)化。

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)

但對(duì)于GROUP BY來說,在MYSQL8.0之前,GROUP Y默認(rèn)會(huì)依據(jù)字段進(jìn)行隱式排序。

可以看到,下面這條sql語句在使用了臨時(shí)表的同時(shí),還進(jìn)行了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)
隱式排序

對(duì)于隱式排序,我們可以參考Mysql官方的解釋:

https://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.html

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 默認(rèn)隱式排序(指在 GROUP BY 列沒有 ASC 或 DESC 指示符的情況下也會(huì)進(jìn)行排序)。然而,GROUP BY進(jìn)行顯式或隱式排序已經(jīng)過時(shí)(deprecated)了,要生成給定的排序順序,請(qǐng)?zhí)峁?ORDER BY 子句。

所以,在Mysql8.0之前,Group by會(huì)默認(rèn)根據(jù)作用字段(Group by的后接字段)對(duì)結(jié)果進(jìn)行排序。在能利用索引的情況下,Group by不需要額外進(jìn)行排序操作;但當(dāng)無法利用索引排序時(shí),Mysql優(yōu)化器就不得不選擇通過使用臨時(shí)表然后再排序的方式來實(shí)現(xiàn)GROUP BY了。

且當(dāng)結(jié)果集的大小超出系統(tǒng)設(shè)置臨時(shí)表大小時(shí),Mysql會(huì)將臨時(shí)表數(shù)據(jù)copy到磁盤上面再進(jìn)行操作,語句的執(zhí)行效率會(huì)變得極低。這也是Mysql選擇將此操作(隱式排序)棄用的原因。


基于上述原因,Mysql在8.0時(shí),對(duì)此進(jìn)行了優(yōu)化更新:

https://dev.mysql.com/doc/refman/8.0/en/order-by-optimization.html

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會(huì)根據(jù)確定的條件進(jìn)行隱式排序。在mysql 8.0中,已經(jīng)移除了這個(gè)功能,所以不再需要通過添加order by null 來禁止隱式排序了,但是,查詢結(jié)果可能與以前的 MySQL 版本不同。要生成給定順序的結(jié)果,請(qǐng)按通過ORDER BY指定需要進(jìn)行排序的字段。

因此,我們的結(jié)論也出來了:

  • 在語義相同,有索引的情況下:

group by和distinct都能使用索引,效率相同。因?yàn)?code style="margin: 0px 2px; padding: 2px 4px; outline: 0px; max-width: 100%; box-sizing: border-box !important; overflow-wrap: break-word !important; border-radius: 4px; background-color: rgba(27, 31, 35, 0.05); font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace; word-break: break-all; color: rgb(255, 93, 108);">group by和distinct近乎等價(jià),distinct可以被看做是特殊的group by

  • 在語義相同,無索引的情況下:

distinct效率高于group by。原因是distinct 和 group by都會(huì)進(jìn)行分組操作,但group by在Mysql8.0之前會(huì)進(jìn)行隱式排序,導(dǎo)致觸發(fā)filesort,sql執(zhí)行效率低下。

但從Mysql8.0開始,Mysql就刪除了隱式排序,所以,此時(shí)在語義相同,無索引的情況下,group by和distinct的執(zhí)行效率也是近乎等價(jià)的。

推薦group by的原因

  1. group by語義更為清晰
  2. group by可對(duì)數(shù)據(jù)進(jìn)行更為復(fù)雜的一些處理

相比于distinct來說,group by的語義明確。且由于distinct關(guān)鍵字會(huì)對(duì)所有字段生效,在進(jìn)行復(fù)合業(yè)務(wù)處理時(shí),group by的使用靈活性更高,group by能根據(jù)分組情況,對(duì)數(shù)據(jù)進(jìn)行更為復(fù)雜的處理,例如通過having對(duì)數(shù)據(jù)進(jìn)行過濾,或通過聚合函數(shù)對(duì)數(shù)據(jù)進(jìn)行運(yùn)算。

版權(quán)聲明:本文為CSDN博主「猾梟」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/weixin_42615847/article/details/118342524


該文章在 2023/3/6 16:33:03 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 日本一本二本三 | 日韩福利在线观看 | 国产爽片在线观看 | 91永久视频在线 | 日韩午夜在线观看 | 丝袜线观看 | 国产国产精品 | 欧美性播放中国 | 国产精品+欧美激情 | 国产中文字幕 | 欧美性XXX| 日本老妇人乱xxy | 成人动漫在线免费看 | 国产女人十八毛 | 国产精品拍综合在线 | 国产网站1区2区 | 91免费视频在线 | 区三区四区 | 午夜影视在线播放免 | 日韩成人午夜视频 | 午夜理论国产 | 国产v欧美v国产 | 日韩亚洲| 91九色中文 | 国产福利在线观看永 | 精品国产亚洲人成在 | 欧美性色高清生活片 | 日本一区二区不卡 | 乱伦精品国产高清 | 三级a三级三级 | 精品二区三区特黄 | 人妖hd| 午夜福利电影在线 | 日韩亚洲国产中 | 国产精品自在线免费 | 午夜视频在 | 中文字幕专区 | 欧美另类重口 | 黑人福利在线 | 韩国电视剧| 欧美在线观看视 |