最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL分組查詢Group By實(shí)現(xiàn)原理詳解

 更新時(shí)間:2016年05月29日 23:41:07   投稿:mdxy-dxy  
在MySQL 中,GROUP BY 的實(shí)現(xiàn)同樣有多種(三種)方式,其中有兩種方式會(huì)利用現(xiàn)有的索引信息來(lái)完成 GROUP BY,另外一種為完全無(wú)法使用索引的場(chǎng)景下使用。下面我們分別針對(duì)這三種實(shí)現(xiàn)方式做一個(gè)分析

由于GROUP BY 實(shí)際上也同樣會(huì)進(jìn)行排序操作,而且與ORDER BY 相比,GROUP BY 主要只是多了排序之后的分組操作。當(dāng)然,如果在分組的時(shí)候還使用了其他的一些聚合函數(shù),那么還需要一些聚合函數(shù)的計(jì)算。所以,在GROUP BY 的實(shí)現(xiàn)過(guò)程中,與 ORDER BY 一樣也可以利用到索引。

  在MySQL 中,GROUP BY 的實(shí)現(xiàn)同樣有多種(三種)方式,其中有兩種方式會(huì)利用現(xiàn)有的索引信息來(lái)完成 GROUP BY,另外一種為完全無(wú)法使用索引的場(chǎng)景下使用。下面我們分別針對(duì)這三種實(shí)現(xiàn)方式做一個(gè)分析。

  1、使用松散(Loose)索引掃描實(shí)現(xiàn) GROUP BY

  何謂松散索引掃描實(shí)現(xiàn) GROUP BY 呢?實(shí)際上就是當(dāng) MySQL 完全利用索引掃描來(lái)實(shí)現(xiàn) GROUP BY 的時(shí)候,并不需要掃描所有滿足條件的索引鍵即可完成操作得出結(jié)果。

  下面我們通過(guò)一個(gè)示例來(lái)描述松散索引掃描實(shí)現(xiàn) GROUP BY,在示例之前我們需要首先調(diào)整一下 group_message 表的索引,將 gmt_create 字段添加到 group_id 和 user_id 字段的索引中:

sky@localhost: example 08:49:45> create index idx_gid_uid_gc
 -> on group_message(group_id,user_id,gmt_create);
 Query OK, rows affected (0.03 sec)
 Records: 96 Duplicates: 0 Warnings: 0
sky@localhost: example 09:07:30> drop index idx_group_message_gid_uid
 -> on group_message;
 Query OK, 96 rows affected (0.02 sec)
 Records: 96 Duplicates: 0 Warnings: 0

然后再看如下 Query 的執(zhí)行計(jì)劃:

sky@localhost: example 09:26:15> EXPLAIN
 -> SELECT user_id,max(gmt_create)
 -> FROM group_message
 -> WHERE group_id < 10
 -> GROUP BY group_id,user_id\G
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: group_message
 type: range
 possible_keys: idx_gid_uid_gc
 key: idx_gid_uid_gc
 key_len: 8
 ref: NULL
 rows: 4
 Extra: Using where; Using index for group-by

我們看到在執(zhí)行計(jì)劃的 Extra 信息中有信息顯示“Using index for group-by”,實(shí)際上這就是告訴我們,MySQL Query Optimizer 通過(guò)使用松散索引掃描來(lái)實(shí)現(xiàn)了我們所需要的 GROUP BY 操作。

下面這張圖片描繪了掃描過(guò)程的大概實(shí)現(xiàn):

要利用到松散索引掃描實(shí)現(xiàn) GROUP BY,需要至少滿足以下幾個(gè)條件:

◆GROUP BY 條件字段必須在同一個(gè)索引中最前面的連續(xù)位置;
◆在使用GROUP BY 的同時(shí),只能使用 MAX 和 MIN 這兩個(gè)聚合函數(shù);
◆如果引用到了該索引中 GROUP BY 條件之外的字段條件的時(shí)候,必須以常量形式存在;

為什么松散索引掃描的效率會(huì)很高?

因?yàn)樵跊](méi)有WHERE子句,也就是必須經(jīng)過(guò)全索引掃描的時(shí)候, 松散索引掃描需要讀取的鍵值數(shù)量與分組的組數(shù)量一樣多,也就是說(shuō)比實(shí)際存在的鍵值數(shù)目要少很多。而在WHERE子句包含范圍判斷式或者等值表達(dá)式的時(shí)候, 松散索引掃描查找滿足范圍條件的每個(gè)組的第1個(gè)關(guān)鍵字,并且再次讀取盡可能最少數(shù)量的關(guān)鍵字。

2.使用緊湊(Tight)索引掃描實(shí)現(xiàn) GROUP BY

緊湊索引掃描實(shí)現(xiàn) GROUP BY 和松散索引掃描的區(qū)別主要在于他需要在掃描索引的時(shí)候,讀取所有滿足條件的索引鍵,然后再根據(jù)讀取惡的數(shù)據(jù)來(lái)完成 GROUP BY 操作得到相應(yīng)結(jié)果。

  sky@localhost : example 08:55:14> EXPLAIN
 -> SELECT max(gmt_create)
 -> FROM group_message
 -> WHERE group_id = 2
 -> GROUP BY user_id\G
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: group_message
 type: ref
 possible_keys: idx_group_message_gid_uid,idx_gid_uid_gc
 key: idx_gid_uid_gc
 key_len: 4
 ref: const
 rows: 4
 Extra: Using where; Using index
 1 row in set (0.01 sec)

這時(shí)候的執(zhí)行計(jì)劃的 Extra 信息中已經(jīng)沒(méi)有“Using index for group-by”了,但并不是說(shuō) MySQL 的 GROUP BY 操作并不是通過(guò)索引完成的,只不過(guò)是需要訪問(wèn) WHERE 條件所限定的所有索引鍵信息之后才能得出結(jié)果。這就是通過(guò)緊湊索引掃描來(lái)實(shí)現(xiàn) GROUP BY 的執(zhí)行計(jì)劃輸出信息。
下面這張圖片展示了大概的整個(gè)執(zhí)行過(guò)程:

在 MySQL 中,MySQL Query Optimizer 首先會(huì)選擇嘗試通過(guò)松散索引掃描來(lái)實(shí)現(xiàn) GROUP BY 操作,當(dāng)發(fā)現(xiàn)某些情況無(wú)法滿足松散索引掃描實(shí)現(xiàn) GROUP BY 的要求之后,才會(huì)嘗試通過(guò)緊湊索引掃描來(lái)實(shí)現(xiàn)。

當(dāng) GROUP BY 條件字段并不連續(xù)或者不是索引前綴部分的時(shí)候,MySQL Query Optimizer 無(wú)法使用松散索引掃描,設(shè)置無(wú)法直接通過(guò)索引完成 GROUP BY 操作,因?yàn)槿笔У乃饕I信息無(wú)法得到。但是,如果 Query 語(yǔ)句中存在一個(gè)常量值來(lái)引用缺失的索引鍵,則可以使用緊湊索引掃描完成 GROUP BY 操作,因?yàn)槌A刻畛淞怂阉麝P(guān)鍵字中的“差距”,可以形成完整的索引前綴。這些索引前綴可以用于索引查找。而如果需要排序GROUP BY結(jié)果,并且能夠形成索引前綴的搜索關(guān)鍵字,MySQL還可以避免額外的排序操作,因?yàn)槭褂糜许樞虻乃饕那熬Y進(jìn)行搜索已經(jīng)按順序檢索到了所有關(guān)鍵字。

3.使用臨時(shí)表實(shí)現(xiàn) GROUP BY

MySQL 在進(jìn)行 GROUP BY 操作的時(shí)候要想利用所有,必須滿足 GROUP BY 的字段必須同時(shí)存放于同一個(gè)索引中,且該索引是一個(gè)有序索引(如 Hash 索引就不能滿足要求)。而且,并不只是如此,是否能夠利用索引來(lái)實(shí)現(xiàn) GROUP BY 還與使用的聚合函數(shù)也有關(guān)系。

前面兩種 GROUP BY 的實(shí)現(xiàn)方式都是在有可以利用的索引的時(shí)候使用的,當(dāng) MySQL Query Optimizer 無(wú)法找到合適的索引可以利用的時(shí)候,就不得不先讀取需要的數(shù)據(jù),然后通過(guò)臨時(shí)表來(lái)完成 GROUP BY 操作。

 sky@localhost : example 09:02:40> EXPLAIN
 -> SELECT max(gmt_create)
 -> FROM group_message
 -> WHERE group_id > 1 and group_id < 10
 -> GROUP BY user_id\G
 *************************** 1. row ***************************
 id: 1
 select_type: SIMPLE
 table: group_message
 type: range
 possible_keys: idx_group_message_gid_uid,idx_gid_uid_gc
 key: idx_gid_uid_gc
 key_len: 4
 ref: NULL
 rows: 32
 Extra: Using where; Using index; Using temporary; Using filesort

這次的執(zhí)行計(jì)劃非常明顯的告訴我們 MySQL 通過(guò)索引找到了我們需要的數(shù)據(jù),然后創(chuàng)建了臨時(shí)表,又進(jìn)行了排序操作,才得到我們需要的 GROUP BY 結(jié)果。整個(gè)執(zhí)行過(guò)程大概如下圖所展示:

當(dāng) MySQL Query Optimizer 發(fā)現(xiàn)僅僅通過(guò)索引掃描并不能直接得到 GROUP BY 的結(jié)果之后,他就不得不選擇通過(guò)使用臨時(shí)表然后再排序的方式來(lái)實(shí)現(xiàn) GROUP BY了。

在這樣示例中即是這樣的情況。 group_id 并不是一個(gè)常量條件,而是一個(gè)范圍,而且 GROUP BY 字段為 user_id。所以 MySQL 無(wú)法根據(jù)索引的順序來(lái)幫助 GROUP BY 的實(shí)現(xiàn),只能先通過(guò)索引范圍掃描得到需要的數(shù)據(jù),然后將數(shù)據(jù)存入臨時(shí)表,然后再進(jìn)行排序和分組操作來(lái)完成 GROUP BY。

相關(guān)文章

  • MySQL性能分析工具profile使用教程

    MySQL性能分析工具profile使用教程

    這篇文章主要介紹了MySQL性能分析工具profile使用教程,本文描述了如何使用MySQL profile,不涉及具體的樣例分析,需要的朋友可以參考下
    2014-10-10
  • MySQL提示表不存在的解決error:1146:Table doesn‘t exist的原因和解決方法

    MySQL提示表不存在的解決error:1146:Table doesn‘t exist的原因和解決

    在使用MySQL的過(guò)程中,有時(shí)會(huì)遇到“Table doesn't exist”(表不存在)的錯(cuò)誤,錯(cuò)誤代碼通常為1146,這個(gè)問(wèn)題可能由多種原因引起,本文將幫助你診斷和解決這個(gè)問(wèn)題,如果遇到同樣問(wèn)題的小伙伴跟著小編一起來(lái)看看吧
    2024-12-12
  • MYSQL大小寫不敏感導(dǎo)致用戶登錄異常問(wèn)題

    MYSQL大小寫不敏感導(dǎo)致用戶登錄異常問(wèn)題

    這篇文章主要介紹了MYSQL大小寫不敏感導(dǎo)致用戶登錄異常問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • MySQL中索引的定義以及操作新手教程

    MySQL中索引的定義以及操作新手教程

    索引是對(duì)數(shù)據(jù)庫(kù)表中一列或多列的值進(jìn)行排序的一種結(jié)構(gòu),在關(guān)系數(shù)據(jù)庫(kù)中,索引是一種與表有關(guān)的數(shù)據(jù)庫(kù)結(jié)構(gòu),下面這篇文章主要給大家介紹了關(guān)于MySQL中索引的定義以及操作的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • MAC系統(tǒng)中添加MYSQL開機(jī)啟動(dòng)的方法

    MAC系統(tǒng)中添加MYSQL開機(jī)啟動(dòng)的方法

    這篇文章主要介紹了MAC系統(tǒng)中添加MYSQL開機(jī)啟動(dòng)的方法,本文簡(jiǎn)潔易懂,步驟清晰,需要的朋友可以參考下
    2014-11-11
  • Mysql中varchar類型一些需要注意的地方

    Mysql中varchar類型一些需要注意的地方

    這篇文章主要介紹了Mysql中varchar類型一些需要注意的地方,幫助大家更好的理解和學(xué)習(xí)MySQL,感興趣的朋友可以了解下
    2021-01-01
  • 關(guān)于MySQL的sql_mode合理設(shè)置詳解

    關(guān)于MySQL的sql_mode合理設(shè)置詳解

    這篇文章主要給大家介紹了關(guān)于MySQL的sql_mode合理設(shè)置的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用MySQL具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • MySQL?中字符集詳細(xì)介紹

    MySQL?中字符集詳細(xì)介紹

    這篇文章主要介紹了MySQL?中字符集詳細(xì)介紹,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-08-08
  • 解讀mysql datetime類型精確到毫秒、微秒的問(wèn)題

    解讀mysql datetime類型精確到毫秒、微秒的問(wèn)題

    這篇文章主要介紹了解讀mysql datetime類型精確到毫秒、微秒的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 如何恢復(fù)MYSQL的ROOT口令

    如何恢復(fù)MYSQL的ROOT口令

    如何恢復(fù)MYSQL的ROOT口令...
    2006-11-11

最新評(píng)論

东阿县| 廊坊市| 利津县| 通州区| 莱芜市| 林州市| 钦州市| 海丰县| 阜康市| 抚顺市| 运城市| 梓潼县| 临沧市| 岐山县| 杭锦旗| 唐海县| 徐汇区| 武鸣县| 耿马| 蓬莱市| 莆田市| 盘山县| 伊通| 临桂县| 麦盖提县| 蒲江县| 固镇县| 嘉定区| 马边| 修文县| 新余市| 枣阳市| 安塞县| 本溪市| 丽水市| 宁晋县| 凌海市| 嘉定区| 赤峰市| 阿鲁科尔沁旗| 兴宁市|