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

MySQL DISTINCT 的基本實現(xiàn)原理詳解

 更新時間:2019年07月11日 10:53:40   作者:Sky.Jian  
這篇文章主要介紹了MySQL DISTINCT 的基本實現(xiàn)原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

前言

DISTINCT 實際上和 GROUP BY 操作的實現(xiàn)非常相似,只不過是在 GROUP BY 之后的每組中只取出一條記錄而已。所以,DISTINCT 的實現(xiàn)和 GROUP BY 的實現(xiàn)也基本差不多,沒有太大的區(qū)別。同樣可以通過松散索引掃描或者是緊湊索引掃描來實現(xiàn),當(dāng)然,在無法僅僅使用索引即能完成 DISTINCT 的時候,MySQL 只能通過臨時表來完成。

但是,和 GROUP BY 有一點差別的是,DISTINCT 并不需要進(jìn)行排序。也就是說,在僅僅只是 DISTINCT 操作的 Query 如果無法僅僅利用索引完成操作的時候,MySQL 會利用臨時表來做一次數(shù)據(jù)的“緩存”,但是不會對臨時表中的數(shù)據(jù)進(jìn)行 filesort 操作。

當(dāng)然,如果我們在進(jìn)行 DISTINCT 的時候還使用了 GROUP BY 并進(jìn)行了分組,并使用了類似于 MAX 之類的聚合函數(shù)操作,就無法避免 filesort 了。

下面我們就通過幾個簡單的 Query 示例來展示一下 DISTINCT 的實現(xiàn)。

1.首先看看通過松散索引掃描完成 DISTINCT 的操作:

sky@localhost : example 11:03:41> EXPLAIN SELECT DISTINCT group_id 
  -> FROM group_messageG
*************************** 1. row ***************************
      id: 1
 SELECT_type: SIMPLE
    table: group_message
     type: range
possible_keys: NULL
     key: idx_gid_uid_gc
   key_len: 4
     ref: NULL
     rows: 10
    Extra: Using index for group-by
1 row in set (0.00 sec)

我們可以很清晰的看到,執(zhí)行計劃中的 Extra 信息為“Using index for group-by”,這代表什么意思?為什么我沒有進(jìn)行 GROUP BY 操作的時候,執(zhí)行計劃中會告訴我這里通過索引進(jìn)行了 GROUP BY 呢?

其實這就是于 DISTINCT 的實現(xiàn)原理相關(guān)的,在實現(xiàn) DISTINCT的過程中,同樣也是需要分組的,然后再從每組數(shù)據(jù)中取出一條返回給客戶端。而這里的 Extra 信息就告訴我們,MySQL 利用松散索引掃描就完成了整個操作。

當(dāng)然,如果 MySQL Query Optimizer 要是能夠做的再人性化一點將這里的信息換成“Using index for distinct”那就更好更容易讓人理解了,呵呵。

2.我們再來看看通過緊湊索引掃描的示例:

sky@localhost : example 11:03:53> EXPLAIN SELECT DISTINCT user_id 
  -> FROM group_message
  -> WHERE group_id = 2G
*************************** 1. row ***************************
      id: 1
 SELECT_type: SIMPLE
    table: group_message
     type: ref
possible_keys: 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.00 sec)

這里的顯示和通過緊湊索引掃描實現(xiàn) GROUP BY 也完全一樣。實際上,這個 Query 的實現(xiàn)過程中,MySQL 會讓存儲引擎掃描 group_id = 2 的所有索引鍵,得出所有的 user_id,然后利用索引的已排序特性,每更換一個 user_id 的索引鍵值的時候保留一條信息,即可在掃描完所有 gruop_id = 2 的索引鍵的時候完成整個 DISTINCT 操作。

3.下面我們在看看無法單獨使用索引即可完成 DISTINCT 的時候會是怎樣:

sky@localhost : example 11:04:40> EXPLAIN SELECT DISTINCT user_id 
  -> FROM group_message
  -> WHERE group_id > 1 AND group_id < 10G
*************************** 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: 4
     ref: NULL
     rows: 32
    Extra: Using WHERE; Using index; Using temporary
1 row in set (0.00 sec)

當(dāng) MySQL 無法僅僅依賴索引即可完成 DISTINCT 操作的時候,就不得不使用臨時表來進(jìn)行相應(yīng)的操作了。但是我們可以看到,在 MySQL 利用臨時表來完成 DISTINCT 的時候,和處理 GROUP BY 有一點區(qū)別,就是少了 filesort。

實際上,在 MySQL 的分組算法中,并不一定非要排序才能完成分組操作的,這一點在上面的 GROUP BY 優(yōu)化小技巧中我已經(jīng)提到過了。實際上這里 MySQL 正是在沒有排序的情況下實現(xiàn)分組最后完成 DISTINCT 操作的,所以少了 filesort 這個排序操作。

4.最后再和 GROUP BY 結(jié)合試試看:

sky@localhost : example 11:05:06> EXPLAIN SELECT DISTINCT max(user_id) 
  -> FROM group_message
  -> WHERE group_id > 1 AND group_id < 10
  -> GROUP BY group_idG
*************************** 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: 4
     ref: NULL
     rows: 32
    Extra: Using WHERE; Using index; Using temporary; Using filesort
1 row in set (0.00 sec)

最后我們再看一下這個和 GROUP BY 一起使用帶有聚合函數(shù)的示例,和上面第三個示例相比,可以看到已經(jīng)多了 filesort 排序操作了,正是因為我們使用了 MAX 函數(shù)的緣故。要取得分組后的 MAX 值,又無法使用索引完成操作,只能通過排序才行了。

由于 DISTINCT的實現(xiàn)基本上和 GROUP BY 的實現(xiàn)差不多,所以這篇文章就不再畫圖展示實現(xiàn)過程了

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解mysql的備份與恢復(fù)

    詳解mysql的備份與恢復(fù)

    這篇文章主要介紹了mysql的備份與恢復(fù)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)mysql,感興趣的朋友可以了解下
    2020-08-08
  • Mysql關(guān)于數(shù)據(jù)庫是否應(yīng)該使用外鍵約束詳解說明

    Mysql關(guān)于數(shù)據(jù)庫是否應(yīng)該使用外鍵約束詳解說明

    MySQL 外鍵約束(FOREIGN KEY)是表的一個特殊字段,經(jīng)常與主鍵約束一起使用。對于兩個具有關(guān)聯(lián)關(guān)系的表而言,相關(guān)聯(lián)字段中主鍵所在的表就是主表,外鍵所在的表就是從表。外鍵用來建立主表與從表的關(guān)聯(lián)關(guān)系,為兩個表的數(shù)據(jù)建立連接,約束兩個表中數(shù)據(jù)的一致性和完整性
    2021-10-10
  • mysql 的root 用戶無法授權(quán)及解決navicat 遠(yuǎn)程授權(quán)提示1044問題

    mysql 的root 用戶無法授權(quán)及解決navicat 遠(yuǎn)程授權(quán)提示1044問題

    這篇文章主要介紹了mysql 的root 用戶無法授權(quán),解決navicat 遠(yuǎn)程授權(quán)提示1044問題,本文通過實例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • SQL如何獲取目標(biāo)時間點或日期的方法實例

    SQL如何獲取目標(biāo)時間點或日期的方法實例

    日期獲取在我們?nèi)粘i_發(fā)中經(jīng)常會遇到,這篇文章主要給大家介紹了關(guān)于SQL如何獲取目標(biāo)時間點或日期的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • MySQL 日期時間加減的示例代碼

    MySQL 日期時間加減的示例代碼

    本文主要介紹了MySQL日期時間加減,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • mySQL服務(wù)器連接,斷開及cmd使用操作

    mySQL服務(wù)器連接,斷開及cmd使用操作

    這篇文章主要介紹了mySQL服務(wù)器連接,斷開及cmd使用操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • MySQL數(shù)據(jù)庫高級數(shù)據(jù)操作之新增數(shù)據(jù)

    MySQL數(shù)據(jù)庫高級數(shù)據(jù)操作之新增數(shù)據(jù)

    這篇文章主要介紹了MySQL數(shù)據(jù)庫高級數(shù)據(jù)操作之新增數(shù)據(jù),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-06-06
  • MySQL中的物理存儲結(jié)構(gòu)詳解

    MySQL中的物理存儲結(jié)構(gòu)詳解

    這篇文章主要介紹了MySQL中的物理存儲結(jié)構(gòu)用法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 深入了解MySQL中分區(qū)表的原理與企業(yè)級實戰(zhàn)

    深入了解MySQL中分區(qū)表的原理與企業(yè)級實戰(zhàn)

    本文詳細(xì)講解什么是分區(qū)表,分區(qū)表增刪改查的工作原理以及分區(qū)表的實戰(zhàn),分區(qū)表的場景有哪些,哪些場景不建議用分區(qū)表,并列舉出六點使用分區(qū)表的誤區(qū),需要的可以參考一下
    2022-11-11
  • SQL實現(xiàn)LeetCode(180.連續(xù)的數(shù)字)

    SQL實現(xiàn)LeetCode(180.連續(xù)的數(shù)字)

    這篇文章主要介紹了SQL實現(xiàn)LeetCode(180.連續(xù)的數(shù)字),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08

最新評論

西峡县| 滨海县| 隆回县| 株洲市| 葫芦岛市| 平顶山市| 安平县| 赞皇县| 新余市| 太仓市| 栾城县| 寿阳县| 东阿县| 黄冈市| 德格县| 樟树市| 扎兰屯市| 会东县| 邹平县| 马边| 岑溪市| 宁明县| 云阳县| 花垣县| 灵丘县| 荥经县| 红安县| 叶城县| 鲁甸县| 贞丰县| 北宁市| 临澧县| 吐鲁番市| 信丰县| 石林| 合水县| 大邑县| 贵德县| 卓资县| 萍乡市| 靖西县|