91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MySQL中的distinct與group?by如何使用

發布時間:2023-03-10 11:45:45 來源:億速云 閱讀:181 作者:iii 欄目:開發技術

這篇文章主要講解了“MySQL中的distinct與group by如何使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“MySQL中的distinct與group by如何使用”吧!

    先說大致的結論 :

    • 在語義相同,有索引的情況下:group bydistinct 都能使用索引,效率相同。

    • 在語義相同,無索引的情況下:distinct 效率高于group by。原因是 distinct 和 group by都會進行分組操作,但group by可能會進行排序,觸發 filesort,導致 sql 執行效率低下。

    基于這個結論,你可能會問:

    • 為什么在語義相同,有索引的情況下,group bydistinct 效率相同?

    • 在什么情況下,group by會進行排序操作?

    帶著這兩個問題找答案。接下來,我們先來看一下 distinctgroup by的基礎使用。

    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 關鍵詞用于返回唯一不同的值。放在查詢語句中的第一個字段前使用,且作用于主句所有列。

    如果列具有 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 |
    +------+
    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,它們的實現都基于分組操作,且都可以通過松散索引掃描、緊湊索引掃描(關于索引掃描的內容會在其他文章中詳細介紹,就不在此細致介紹了)來實現。

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

    所以,在一般情況下,對于相同語義的DISTINCTGROUP 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 bydistinct 都能使用索引,效率相同。因為group bydistinct近乎等價,distinct 可以被看做是特殊的group by

    • 在語義相同,無索引的情況下: distinct效率高于group by。原因是distinctgroup by都會進行分組操作,但group by在 MySQL8.0 之前會進行隱式排序,導致觸發 filesort,sql 執行效率低下。但從 MySQL8.0 開始,MySQL 就刪除了隱式排序,所以,此時在語義相同,無索引的情況下,group bydistinct的執行效率也是近乎等價的。

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

    感謝各位的閱讀,以上就是“MySQL中的distinct與group by如何使用”的內容了,經過本文的學習后,相信大家對MySQL中的distinct與group by如何使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    江陵县| 崇明县| 鄢陵县| 广安市| 财经| 阳春市| 启东市| 荔波县| 宿迁市| 焉耆| 广州市| 江源县| 邵阳市| 五峰| 图们市| 铜川市| 三江| 和林格尔县| 四川省| 深水埗区| 淮南市| 吉首市| 高雄县| 于田县| 屯留县| 长子县| 弥勒县| 仁化县| 绥芬河市| 邻水| 扬中市| 和田县| 象州县| 阿拉善左旗| 瓦房店市| 永年县| 那坡县| 泰州市| 宝兴县| 进贤县| 广河县|