<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
先說大致的結論 :
group by
和 distinct
都能使用索引,效率相同。distinct
效率高於group by
。原因是 distinct 和 group by
都會進行分組操作,但group by
可能會進行排序,觸發 filesort,導致 sql 執行效率低下。基於這個結論,你可能會問:
group by
和 distinct
效率相同?group by
會進行排序操作?帶著這兩個問題找答案。接下來,我們先來看一下 distinct
和group by
的基礎使用。
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
關鍵詞用於返回唯一不同的值。放在查詢語句中的第一個欄位前使用,且作用於主句所有列。
如果列具有 NULL 值,並且對該列使用DISTINCT
子句,MySQL 將保留一個 NULL 值,並刪除其它的 NULL 值,因為DISTINCT
子句將所有 NULL 值視為相同的值。
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
的使用和 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 | +------+ 4 rows in set (0.02 sec)
語法:
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
都是可以使用索引進行掃描搜尋的。例如以下兩條 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 官方的解釋:
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 預設隱式排序(指在 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 時,對此進行了優化更新:
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 會根據確定的條件進行隱式排序。在 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
的執行效率也是近乎等價的。相比於distinct
來說,group by
的語意明確。且由於 distinct 關鍵字會對所有欄位生效,在進行復合業務處理時,group by
的使用靈活性更高,group by
能根據分組情況,對資料進行更為複雜的處理,例如通過having
對資料進行過濾,或通過聚合函數對資料進行運算。
到此這篇關於MySQL中的distinct與group by比較使用方法的文章就介紹到這了,更多相關MySQL distinct與group by內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45