精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Count(distinct) 玩出了新花樣

數(shù)據(jù)庫 MySQL
MySQL 使用 MEMORY 引擎臨時(shí)表實(shí)現(xiàn) count(distinct) 的去重功能時(shí),玩出了新花樣,所以,還是值得寫一下的。背景說明到此為止,我們快快開始。

介紹使用索引、臨時(shí)表 + 文件排序?qū)崿F(xiàn) group by,以及單獨(dú)介紹臨時(shí)表的三篇文章中,多次以 count(distinct) 作為示例說明。

那還有必要單獨(dú)為 count(distinct) 寫一篇文章嗎?

此刻,想到一句臺(tái)詞:別問,問就是有必要。

回到正題,MySQL 使用 MEMORY 引擎臨時(shí)表實(shí)現(xiàn) count(distinct) 的去重功能時(shí),玩出了新花樣,所以,還是值得寫一下的。背景說明到此為止,我們快快開始。

本文內(nèi)容基于 MySQL 5.7.35 源碼。

1、 概述

如果 count(distinct) 不能使用索引去重,就需要使用臨時(shí)表。臨時(shí)表的存儲(chǔ)引擎有三種選擇:MEMORY、MyISAM、InnoDB。

和使用 MyISAM 或 InnoDB 作為臨時(shí)表的存儲(chǔ)引擎處理邏輯有些不一樣,如果 MySQL 決定使用 MEMORY 作為臨時(shí)表的存儲(chǔ)引擎,臨時(shí)表會(huì)被創(chuàng)建,但只是作為輔助,表里不會(huì)寫入任何數(shù)據(jù)。

要說清楚為什么會(huì)有這種花樣操作,需要從 MEMORY 引擎支持的兩種索引結(jié)構(gòu)說起。

2、 MEMORY 支持的兩種索引結(jié)構(gòu)

MEMORY 引擎支持兩種索引結(jié)構(gòu):HASH 索引、B-TREE 索引。

HASH 索引,顧名思義,索引的數(shù)據(jù)結(jié)構(gòu)是哈希表。hash key 是索引字段內(nèi)容計(jì)算得到的哈希值,hash value 是索引記錄指向的數(shù)據(jù)行的地址。

HASH 索引中的記錄不是按照字段內(nèi)容順序存放的,而是亂序的,其優(yōu)點(diǎn)在于查找時(shí)間復(fù)雜度是 O(1),按單個(gè)值查找記錄速度非???,但不能用于范圍查詢。

HASH 索引結(jié)構(gòu)示意圖

MyISAM、InnoDB 引擎 B-TREE 索引的數(shù)據(jù)結(jié)構(gòu)是 B+ 樹,而 MEMORY 引擎 B-TREE 索引的數(shù)據(jù)結(jié)構(gòu)是紅黑樹。

B-TREE 索引結(jié)構(gòu)示意圖

MEMORY 引擎的 B-TREE 索引結(jié)點(diǎn)中保存著索引字段內(nèi)容,以及對(duì)應(yīng)數(shù)據(jù)行的地址。

紅黑樹是平衡二叉排序樹,因此 B-TREE 索引中的結(jié)點(diǎn)是排好序的,支持范圍查詢,但是按單個(gè)值查找記錄的時(shí)間復(fù)雜度是 O(logN),相比于 HASH 索引來說要低一些。

基于兩種數(shù)據(jù)結(jié)構(gòu)的特點(diǎn),HASH 索引適用于單值查找場(chǎng)景,B-TREE 索引適用于范圍查詢和需要排好序的記錄的場(chǎng)景。

3、去重方案怎么選?

說完了 MEMORY 引擎的兩種索引結(jié)構(gòu),以及它們的適用場(chǎng)景,再來介紹 count(distinct) 去重方案就有基礎(chǔ)了。

按照常規(guī)流程走,當(dāng) MySQL 選擇使用 MEMORY 作為臨時(shí)表的存儲(chǔ)引擎,加上為 distinct 字段創(chuàng)建的 HASH 索引,這完全能實(shí)現(xiàn)去重操作。但是本著節(jié)約精神,MySQL 向來是能省則省,只要有優(yōu)化方案,一定是要使用的,那還可以怎么優(yōu)化呢?

要回答這個(gè)問題,我們需要先抓住去重功能的關(guān)鍵,那就是表中記錄的唯一性。

臨時(shí)表中為 distinct 創(chuàng)建的 HASH 索引默認(rèn)就是唯一索引,既然 HASH 索引本身就保證了唯一性,是不是可以考慮只使用 HASH 索引實(shí)現(xiàn) count(distinct) 的去重功能呢?

這種思路是可行的,不過 MEMORY 引擎的 HASH 索引有一個(gè)不能滿足要求的地方:HASH 索引中沒有保存索引字段內(nèi)容,只保存了字段內(nèi)容的 hash 值。

只用索引的數(shù)據(jù)結(jié)構(gòu)去重為什么需要保存字段內(nèi)容,介紹去重過程的時(shí)候會(huì)說明,在那個(gè)場(chǎng)景下解釋起來更好理解一點(diǎn),這里先按下不表。

既然 HASH 索引不能滿足要求,別忘了 MEMORY 引擎還支持另一種索引結(jié)構(gòu):B-TREE 索引。B-TREE 索引也能實(shí)現(xiàn)去重功能,索引結(jié)點(diǎn)中還保存了字段內(nèi)容,完美符合要求。

前面以流式的方式介紹了三種候選的去重方案,我們需要來個(gè)小結(jié):

方案一,臨時(shí)表 + HASH 索引,這種實(shí)現(xiàn)方案中規(guī)中矩,能夠滿足需求,缺點(diǎn)在于:只是為了實(shí)現(xiàn)去重功能,HASH 索引自己上陣就夠了,可偏偏還要搭上更多內(nèi)存往表里寫一份數(shù)據(jù),浪費(fèi)寶貴的內(nèi)存資源。

方案二,方案一中說到,HASH 索引自己就能夠?qū)崿F(xiàn)去重了,這點(diǎn)毋庸置疑,只使用 HASH 索引也是候選方案之一,但 HASH 索引中沒有保存索引字段內(nèi)容,只能無奈的出局了。

方案三,B-TREE 索引,既能實(shí)現(xiàn)去重功能,索引中還保存了字段內(nèi)容,完美,就是它了。

不過,MySQL 沒有在 MEMORY 臨時(shí)表上再創(chuàng)建一個(gè) B-TREE 類型的唯一索引,而是用了 B-TREE 索引所使用的紅黑樹,并且因?yàn)榕R時(shí)表中不會(huì)寫入任何數(shù)據(jù),紅黑樹結(jié)點(diǎn)中只需要保存字段內(nèi)容,不需要保存指向表中數(shù)據(jù)行的地址。

再次說明:MEMORY 臨時(shí)表還是會(huì)創(chuàng)建,但是不會(huì)寫入任何數(shù)據(jù),就是空表。紅黑樹實(shí)現(xiàn)去重功能的過程中,會(huì)用到 MEMORY 臨時(shí)表的字段信息、記錄緩沖區(qū)。

以后,用 explain 查看執(zhí)行計(jì)劃時(shí),如果發(fā)現(xiàn) count(distinct) 既沒有使用索引,也沒有使用臨時(shí)表,那你可能就會(huì)想到:這家伙大概是悄無聲息的使用了紅黑樹。

前面說了這么多,只是為了弄清楚一個(gè)問題:為什么選擇紅黑樹實(shí)現(xiàn)去重功能。這很重要,我們要知其然,更要知其所以然,這樣我們理解起來也會(huì)更容易些,你說是嗎?

接下來我們就要說說紅黑樹實(shí)現(xiàn) count(distinct) 去重功能的點(diǎn)點(diǎn)滴滴了。

4、 紅黑樹結(jié)點(diǎn)存了些什么?

紅黑樹是平衡二叉排序樹,既然是二叉樹結(jié)構(gòu),就會(huì)有指向左子樹、右子樹的指針。

紅黑樹的結(jié)點(diǎn)分為紅色和黑色,自然要有個(gè)屬性來標(biāo)記結(jié)點(diǎn)顏色。

MySQL 實(shí)現(xiàn)的紅黑樹,還支持插入重復(fù)結(jié)點(diǎn),這是通過在結(jié)點(diǎn)中增加一個(gè)記錄結(jié)點(diǎn)內(nèi)容重復(fù)次數(shù)的屬性實(shí)現(xiàn)的。

以上信息都屬于結(jié)點(diǎn)元數(shù)據(jù),元數(shù)據(jù)占用 24 字節(jié)內(nèi)存空間。每一個(gè)結(jié)點(diǎn)中,除了保存著結(jié)點(diǎn)元數(shù)據(jù),還要保存結(jié)點(diǎn)數(shù)據(jù),就是字段內(nèi)容。

結(jié)點(diǎn)元數(shù)據(jù)

5、 紅黑樹占用內(nèi)存太大怎么辦?

使用紅黑樹去重雖然不用往 MEMORY 臨時(shí)表寫入數(shù)據(jù),但是紅黑樹也不能無限制占用內(nèi)存。

它能夠占用的最大內(nèi)存和 MEMORY 引擎臨時(shí)表一樣,也是由 tmp_table_size、max_heap_table_size 兩個(gè)系統(tǒng)變量中較小的的那個(gè)決定的。默認(rèn)配置下,紅黑樹能夠占用的最大內(nèi)存為 16M。

既然內(nèi)存大小有限制,那就可能會(huì)出現(xiàn)紅黑樹中沒有空間容納新結(jié)點(diǎn)的情況,此時(shí),磁盤文件就要粉墨登場(chǎng)了。

如果紅黑樹占用內(nèi)存達(dá)到最大值,所有結(jié)點(diǎn)數(shù)據(jù)(不包含元數(shù)據(jù))會(huì)被寫入磁盤文件,然后刪除紅黑樹所有結(jié)點(diǎn),保留內(nèi)存以便重復(fù)使用。

這些一起寫入磁盤文件的數(shù)據(jù)會(huì)組成一個(gè)數(shù)據(jù)塊,數(shù)據(jù)塊的相關(guān)信息(在磁盤文件中的位置、記錄數(shù)量)保存在對(duì)應(yīng)的 Merge_chunk 中。

磁盤文件中可能會(huì)有多個(gè)數(shù)據(jù)塊。

數(shù)據(jù)塊相關(guān)信息

數(shù)據(jù)塊中的數(shù)據(jù),因?yàn)閬碓从诩t黑樹,有兩個(gè)特點(diǎn):

  • 記錄是按照字段內(nèi)容從小到大順序存放的。
  • 記錄的字段內(nèi)容是唯一的,不存在重復(fù)。

數(shù)據(jù)塊中的數(shù)據(jù)

6、合并緩沖區(qū)

通過上一小節(jié),我們知道紅黑樹占用內(nèi)存達(dá)到最大值之后,會(huì)生成一個(gè)數(shù)據(jù)塊寫入到磁盤文件。

所謂天下大勢(shì),合久必分,分久必合。

磁盤文件中的數(shù)據(jù)塊,雖然是分開寫入的,但終究要合并去重,并進(jìn)行分組計(jì)數(shù)。

磁盤文件中的每個(gè)數(shù)據(jù)塊內(nèi)部,記錄的字段內(nèi)容是不存在重復(fù)的。但是,多個(gè)數(shù)據(jù)塊之間的字段內(nèi)容可能存在重復(fù),合并過程中,需要對(duì)多個(gè)數(shù)據(jù)塊之間的字段內(nèi)容去重。

合并去重,有兩種可選的實(shí)現(xiàn)方案:

方案一,分為三步:

① 從磁盤文件的每個(gè)數(shù)據(jù)塊中讀取剩余記錄里最小的一條記錄到內(nèi)存中,最小的記錄其實(shí)就是剩余記錄里的第一條記錄。

② 找出第 ① 步讀取的那些記錄中最小的記錄。

③ 判斷當(dāng)前的最小記錄,是否和上一次最小的記錄相同,如果相同,說明重復(fù),不處理;如果不同,進(jìn)行計(jì)數(shù)。

循環(huán)執(zhí)行第 ① ~ ③ 步,直到讀完當(dāng)前分組所有數(shù)據(jù)塊中的記錄,合并完成。

從以上描述中,想必大家已經(jīng)發(fā)現(xiàn)了這種方案存在的問題:需要頻繁的從磁盤文件中讀取數(shù)據(jù),每次還只讀取一條記錄,頻繁磁盤 IO 必然會(huì)影響 SQL 語句執(zhí)行效率,為此,就有了方案二。

方案二,既然不能頻繁從磁盤中讀取數(shù)據(jù),那就換個(gè)方式,每次讀取一批記錄,減少讀取次數(shù)。

但是,一批記錄和一條記錄不一樣,需要找個(gè)大點(diǎn)的地方臨時(shí)存放,于是就有了合并緩沖區(qū)。

合并緩沖區(qū)的大小和紅黑樹占用內(nèi)存最大值一樣,也是由 tmp_table_size、max_heap_table_size 兩個(gè)系統(tǒng)變量中較小的那個(gè)控制的,默認(rèn)大小為 16M。

合并緩沖區(qū)會(huì)分成 N 份(N = 磁盤文件中數(shù)據(jù)塊的數(shù)量),每一份對(duì)應(yīng)一個(gè)數(shù)據(jù)塊,用于存放從數(shù)據(jù)塊中讀取的一批記錄。

合并緩沖區(qū)

7、 紅黑樹怎么去重和分組計(jì)數(shù)?

介紹完了前置知識(shí)點(diǎn),重頭戲來了,該說說紅黑樹去重和分組計(jì)數(shù)的過程了。

為了方便描述,我們還是結(jié)合一個(gè)具體 SQL 來介紹,示例表及 SQL 如下:

CREATE TABLE `t_group_by` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`e1` enum('北京','上海','廣州','深圳','天津','杭州','成都','重慶','蘇州','南京','哈爾濱','沈陽','長春','廈門','福州','南昌','泉州','德清','長沙','武漢') DEFAULT '北京',
`i1` int(10) unsigned DEFAULT '0',
`c1` char(11) DEFAULT '',
`d1` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_e1` (`e1`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

select
e1, count(distinct i1)
from t_group_by
group by e1

在調(diào)試過程中,我給 t_group_by 表的 e1 字段建了索引,所以 SQL 執(zhí)行時(shí)就不需要先對(duì)表中記錄進(jìn)行排序了。

先來看一下去重及分組計(jì)數(shù)過程的示意圖。

去重及分組計(jì)數(shù)主流程

看完上面的示意圖,想必大家對(duì)整個(gè)過程有個(gè)大致的印象了,我們?cè)龠M(jìn)一步看看過程中的每一步都會(huì)做哪些事情。

第 1 步,讀取記錄。

從 from 子句的表中讀取一條記錄,示例 SQL 中為 t_group_by 表。

第 2 步,判斷紅黑樹是否寫滿。

前面介紹過,紅黑樹的一個(gè)結(jié)點(diǎn)中包含兩類信息:

  • 結(jié)點(diǎn)元數(shù)據(jù),占用 24 字節(jié)。
  • 結(jié)點(diǎn)數(shù)據(jù),示例 SQL 中結(jié)點(diǎn)數(shù)據(jù)就是 i1 字段內(nèi)容,長度為 4 字節(jié)。

示例 SQL 中,一個(gè)紅黑樹結(jié)點(diǎn)占用 24 + 4 = 28 字節(jié)。

知道紅黑樹最大能占用的內(nèi)存,每個(gè)結(jié)點(diǎn)占用的內(nèi)存,就能夠算出紅黑樹最多可以插入多少個(gè)結(jié)點(diǎn)了,也就能夠很方便的判斷出紅黑樹是不是滿了。

如果紅黑樹已滿,進(jìn)入第 3 步,把紅黑樹中所有結(jié)點(diǎn)數(shù)據(jù)寫入磁盤文件。

如果紅黑樹沒滿,進(jìn)入第 4 步,插入新結(jié)點(diǎn)。

第 3 步,把紅黑樹所有結(jié)點(diǎn)數(shù)據(jù)寫入磁盤文件。

按照中序遍歷,把紅黑樹中所有結(jié)點(diǎn)數(shù)據(jù)按順序?qū)懭氪疟P文件。結(jié)點(diǎn)元數(shù)據(jù)此時(shí)就不需要了,不會(huì)寫入磁盤文件。

前面介紹過這些數(shù)據(jù)會(huì)組成一個(gè)數(shù)組塊,每個(gè)數(shù)據(jù)塊的相關(guān)信息保存在對(duì)應(yīng)的 Merge_chunk 類實(shí)例中。

數(shù)據(jù)寫入磁盤后,紅黑樹會(huì)刪除所有結(jié)點(diǎn),但是內(nèi)存空間會(huì)保留復(fù)用。此時(shí),紅黑樹就是空的了,進(jìn)入第 4 步,把剛剛因?yàn)榧t黑樹已滿沒有插入的節(jié)點(diǎn)插入到空的紅黑樹中。

第 4 步,插入新結(jié)點(diǎn)。

從 t_group_by 表讀取一條記錄之后,i1 字段值作為新結(jié)點(diǎn)的數(shù)據(jù)插入到紅黑樹中,然后回到第 1 步繼續(xù)執(zhí)行。

第 1 ~ 4 步是循環(huán)執(zhí)行的,直到一個(gè)分組的所有數(shù)據(jù)都插了入紅黑樹,循環(huán)過程結(jié)束,進(jìn)入第 5 步。

第 5 步,處理 count(distinct) 聚合邏輯。

處理聚合邏輯分兩種情況:

  • 沒有使用磁盤文件,分組記錄少,紅黑樹一次都沒有寫滿過,所有數(shù)據(jù)都在內(nèi)存中。
  • 使用了磁盤文件,分組記錄多,紅黑樹寫滿過,前面 N - 1 次寫滿之后,數(shù)據(jù)寫入磁盤文件,最后一次數(shù)據(jù)留在內(nèi)存中。

如果沒有使用磁盤文件,進(jìn)入第 6 步。

如果使用了磁盤文件,進(jìn)入第 7 步。

第 6 步,分組計(jì)數(shù)。

紅黑樹所有結(jié)點(diǎn)都在內(nèi)存中,紅黑樹中的結(jié)點(diǎn)數(shù)量就是 count(distinct) 函數(shù)的結(jié)果。這個(gè)步驟處理完,流程結(jié)束。

第 7 步,多個(gè)數(shù)據(jù)塊合并去重,然后分組計(jì)數(shù)。

紅黑樹寫滿過,部分?jǐn)?shù)據(jù)在磁盤文件中,部分?jǐn)?shù)據(jù)在內(nèi)存中。需要先把內(nèi)存中紅黑樹所有結(jié)點(diǎn)數(shù)據(jù)寫入到磁盤文件中,組成最后一個(gè)數(shù)據(jù)塊。

所有數(shù)據(jù)都寫入磁盤文件之后,就可以開始進(jìn)行合并去重和分組計(jì)數(shù)了。

首先,分配一塊內(nèi)存作為合并緩沖區(qū)。

然后,把緩沖區(qū)平均分成 N 份,為了描述方便,我們把緩沖區(qū)的 N 分之一叫作子緩沖區(qū)。假設(shè)示例 SQL 在磁盤文件中有 4 個(gè)數(shù)據(jù)塊,就會(huì)對(duì)應(yīng) 4 個(gè)子緩沖區(qū)。

每一個(gè)數(shù)據(jù)塊對(duì)應(yīng)的 Merge_chunk 中保存著子緩沖區(qū)的開始和結(jié)束位置、能夠存放的記錄數(shù)量、指向子緩沖區(qū)中下一條要處理的記錄的位置。

合并緩沖區(qū)

每個(gè)數(shù)據(jù)塊內(nèi)部的記錄都是按照字段內(nèi)容從小到大排好序的,多個(gè)數(shù)據(jù)塊合并去重的過程不算復(fù)雜,步驟如下:

合并去重及分組計(jì)數(shù)流程

① 讀取磁盤文件中的數(shù)據(jù)塊到子緩沖區(qū)。

從每個(gè)數(shù)據(jù)塊讀取一部分記錄到子緩沖區(qū),所有數(shù)據(jù)塊對(duì)應(yīng)的 Merge_chunk 組成一個(gè)優(yōu)先隊(duì)列。

此時(shí),每個(gè) Merge_chunk 的 m_current_key 都指向數(shù)據(jù)塊的第一條記錄,也是該數(shù)據(jù)塊中最小的記錄,這條記錄的內(nèi)容就代表 Merge_chunk 的值。

Merge_chunk 的 m_mem_count 表示已讀取到子緩沖區(qū)中尚未處理的記錄數(shù)量。

② 獲取優(yōu)先隊(duì)列中最小的 Merge_chunk,用top表示。

優(yōu)先隊(duì)列中第一個(gè) Merge_chunk 就是所有 Merge_chunk 中最小的。

③ 讀取 top Merge_chunk 的 m_current_key 指向的記錄的內(nèi)容到 old_key。

m_current_key 指向的記錄就是 top Merge_chunk 中的最小記錄,記為 old_key。

然后,m_current_key 指向數(shù)據(jù)塊中下一條記錄,m_mem_count 減 1,表示已讀取到子緩沖區(qū)中的尚未處理的記錄減少 1 條。

④ 如果 m_mem_count 等于 0,說明該數(shù)據(jù)塊對(duì)應(yīng)子緩沖區(qū)中的記錄已處理完,需要再從磁盤文件中讀取該數(shù)據(jù)塊的一部分記錄到子緩沖區(qū)。

如果數(shù)據(jù)塊中的數(shù)據(jù)都已處理完,把數(shù)據(jù)塊對(duì)應(yīng)的 Merge_chunk 從優(yōu)先隊(duì)列中刪除,對(duì)應(yīng)子緩沖區(qū)的內(nèi)存空間全部并入相鄰的子緩沖區(qū)。

⑤ 更新優(yōu)先隊(duì)列中的 top Merge_chunk。

③、④ 兩步執(zhí)行之后,最小的 Merge_chunk 可能發(fā)生了變化,所以需要更新優(yōu)先隊(duì)列,保證優(yōu)先隊(duì)列中的第一個(gè) Merge_chunk 是最小的。

⑥ 真正的去重操作。

比較新的 top Merge_chunk 中最小記錄的內(nèi)容和 old_key的值,如果一樣,說明字段內(nèi)容重復(fù),不需要進(jìn)行分組計(jì)數(shù),回到 ③ ,繼續(xù)進(jìn)行下一輪循環(huán)。

如果不一樣,說明字段內(nèi)容不重復(fù),對(duì) top Merge_chunk 中的最小記錄進(jìn)行分組計(jì)數(shù),然后回到 ③ ,繼續(xù)進(jìn)行下一輪循環(huán)。

③ ~ ⑥ 是循環(huán)執(zhí)行的,直到優(yōu)先隊(duì)列中 Merge_chunk 的數(shù)量小于等于 1 個(gè),循環(huán)結(jié)束。

⑦ 處理最后一個(gè)數(shù)據(jù)塊中剩余的數(shù)據(jù)。

經(jīng)過 ③ ~ ⑥ 循環(huán)執(zhí)行過程,優(yōu)先隊(duì)列中還會(huì)剩下 1 個(gè) Merge_chunk,需要對(duì) Merge_chunk 對(duì)應(yīng)數(shù)據(jù)塊中剩下的記錄進(jìn)行分組計(jì)數(shù),因?yàn)槭且粋€(gè)數(shù)據(jù)塊內(nèi)部的記錄,就不需要去重了。

前面那個(gè)按下不表的問題也該有下文了:

因?yàn)閷?duì)磁盤文件多個(gè)數(shù)據(jù)塊中的記錄合并去重時(shí),需要使用字段內(nèi)容做比較,而 MEMORY 引擎的 HASH 索引中沒有保存字段內(nèi)容,只保存了表中數(shù)據(jù)行的首地址,這就是 MySQL 選擇使用紅黑樹去重,而沒有選擇 HASH 的原因。

8、 sum(distinct)、avg(distinct) 不一樣

sum(distinct)、avg(distinct) 也需要去重,但是和 count(distinct) 不一樣的地方在于:sum(distinct)、avg(distinct) 只會(huì)對(duì)整數(shù)、浮點(diǎn)數(shù)求和或求平均數(shù),并且只能有一個(gè)參數(shù),需要的內(nèi)存空間比較小,這意味著 sum(distinct)、avg(distinct) 去重時(shí)不需要用磁盤臨時(shí)表。

因此,對(duì)于 sum(distinct)、avg(distinct) 來說,只會(huì)選擇使用紅黑樹去重,并且也不會(huì)創(chuàng)建一個(gè)空的 MEMORY 臨時(shí)表,這兩點(diǎn)和 count(distinct) 不一樣。

如果 sum()、avg() 函數(shù)參數(shù)中的字段不是整數(shù)或浮點(diǎn)數(shù)類型的字段,不會(huì)報(bào)錯(cuò),字段值都會(huì)被轉(zhuǎn)換為浮點(diǎn)數(shù),然后對(duì)浮點(diǎn)數(shù)求和或求平均數(shù)。

非整數(shù)、浮點(diǎn)數(shù)類型字段轉(zhuǎn)換為浮點(diǎn)數(shù),和開發(fā)語言中的轉(zhuǎn)換邏輯基本相同,對(duì)于字符串內(nèi)容,就是把字符串前面的數(shù)字作為字段的數(shù)字值,例如:91 測(cè)試轉(zhuǎn)換為浮點(diǎn)數(shù)是 91.0,測(cè)試轉(zhuǎn)換為浮點(diǎn)數(shù)是 0.0。

9、 總結(jié)

第 2 小節(jié),介紹了 MEMORY 引擎支持的兩種索引結(jié)構(gòu):HASH 索引、B-TREE 索引。

HASH 索引適用于單值查找多的場(chǎng)景;B-TREE 索引適用于范圍查詢、需要排好序的記錄的場(chǎng)景。

第 3 小節(jié),以循序漸進(jìn)的方式介紹了 MySQL 為什么選擇使用紅黑樹實(shí)現(xiàn) count(distinct) 的去重功能。

第 4 小節(jié),介紹了紅黑樹單個(gè)結(jié)點(diǎn)的結(jié)構(gòu),每個(gè)結(jié)點(diǎn)包含結(jié)點(diǎn)元數(shù)據(jù)、結(jié)點(diǎn)數(shù)據(jù)兩類信息。

第 5 小節(jié),介紹了紅黑樹占用內(nèi)存超過最大值之后,會(huì)把所有結(jié)點(diǎn)數(shù)據(jù)寫入磁盤文件,然后刪除所有結(jié)點(diǎn),保留內(nèi)存重復(fù)使用。

第 6 小節(jié),以循序漸進(jìn)的方式介紹了為什么需要合并緩沖區(qū),以及緩沖區(qū)的大小由 tmp_table_size、max_heap_table_size 兩個(gè)系統(tǒng)變量控制。

第 7 小節(jié),介紹了磁盤文件中所有數(shù)據(jù)塊合并去重、分組計(jì)數(shù)的詳細(xì)過程。合并去重及分組計(jì)數(shù)分為紅黑樹寫滿過、沒寫滿過兩種情況,處理邏輯不一樣。

第 8 小節(jié),介紹了 sum(distinct)、avg(distinct) 只能用于整數(shù)、浮點(diǎn)數(shù)求和、求平均數(shù),它們和 count(distinct) 不一樣的地方在于:只會(huì)選擇使用紅黑樹去重,不需要?jiǎng)?chuàng)建 MEMORY 臨時(shí)表,更不需要磁盤臨時(shí)表。

本文轉(zhuǎn)載自微信公眾號(hào)「一樹一溪」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系一樹一溪公眾號(hào)。

責(zé)任編輯:姜華 來源: 一樹一溪
相關(guān)推薦

2019-07-23 11:20:16

2017-05-22 15:50:38

ICT華為生態(tài)之行

2025-09-09 01:25:00

2024-06-11 09:52:39

2012-11-20 16:23:19

飛輪UPS數(shù)據(jù)中心電源

2025-03-04 07:53:40

2013-10-22 09:37:14

網(wǎng)絡(luò)配置管理網(wǎng)絡(luò)性能監(jiān)控

2021-01-04 11:14:09

品牌營銷UGC

2009-05-13 20:12:15

殺毒設(shè)計(jì)師H1N1

2013-01-22 11:22:02

聯(lián)想Yoga

2023-03-17 16:47:46

圖像特技

2021-07-04 17:00:00

數(shù)字人民幣微信支付寶

2022-05-30 08:01:25

Windows 11操作系統(tǒng)桌面貼紙

2022-07-15 13:14:37

AI技術(shù)NeRFdeepfakes

2022-09-14 12:00:51

React路由庫前端

2010-09-01 13:47:42

釣魚網(wǎng)站
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

懂色av中文在线| 特级毛片www| 国产免费av国片精品草莓男男| 亚洲欧美一区二区三区国产精品 | 精品无人国产偷自产在线| 国产中文字幕在线免费观看| 户外极限露出调教在线视频| 精品中文字幕一区二区小辣椒| 欧美极品少妇xxxxⅹ喷水 | 嫩草国产精品入口| 欧美中文字幕一二三区视频| 无颜之月在线看| 高清日韩av电影| 夫妻av一区二区| 国产精品激情av电影在线观看| 裸体武打性艳史| 妖精视频一区二区三区| 欧美一区二区三区小说| 国产熟女高潮视频| av在线网页| 中文字幕亚洲欧美在线不卡| 久久riav二区三区| av在线亚洲天堂| 日本在线播放一区二区三区| 性金发美女69hd大尺寸| 国产精品久久久久久久av| 国产成人高清精品免费5388| 欧美精品tushy高清| 六月激情综合网| 国产精品186在线观看在线播放| 国产精品视频免费看| 久久人人97超碰人人澡爱香蕉| 国产毛片毛片毛片毛片| 奇米一区二区三区| 国产va免费精品高清在线| 久久久精品国产sm调教网站| 91麻豆精品国产91久久久平台| 亚洲美女激情视频| www男人天堂| 亚洲日本va中文字幕| 欧美电影一区二区| 欧美激情第3页| 国产香蕉久久| 欧美三级日韩在线| 凹凸日日摸日日碰夜夜爽1| 日韩伦理在线一区| 第一福利永久视频精品 | 成熟人妻av无码专区| 婷婷综合一区| 亚洲男女性事视频| 中文字幕一二三四区| 午夜先锋成人动漫在线| 日韩av一区二区在线| 艳妇乳肉豪妇荡乳xxx| 久久综合给合| 日韩精品在线看片z| 在线观看免费看片| 亚洲国产中文在线| 欧美成人官网二区| 日本性生活一级片| 粉嫩的18在线观看极品精品| 亚洲精品在线观| 秘密基地免费观看完整版中文 | 精品成人一区二区三区四区| 女教师高潮黄又色视频| 澳门精品久久国产| 亚洲精品电影在线| 人妻少妇无码精品视频区| 深爱激情久久| 中文字幕亚洲欧美| 五月天色婷婷丁香| 伊人蜜桃色噜噜激情综合| 91精品国产91久久久久久久久| 日韩污视频在线观看| 亚洲另类视频| 国产精品成人一区二区| 亚洲一区中文字幕永久在线| 精品一区二区三区久久| 51国偷自产一区二区三区| 黄色aaa毛片| 久久伊99综合婷婷久久伊| 日韩欧美一区二区视频在线播放| 日韩黄色影院| 亚洲国产精品一区二区久久恐怖片| 日韩一级性生活片| 香蕉视频亚洲一级| 91精品国产综合久久久久久| 伊人av在线播放| 三级精品视频| www欧美日韩| 精品少妇一二三区| 视频一区二区不卡| 亚洲影院色无极综合| 天堂网av2014| 亚洲三级在线播放| 久久久久久久久久久福利| 四虎影视精品永久在线观看| 精品国产一区二区三区不卡| 天堂久久精品忘忧草| 这里只有精品在线| 欧美一级大片视频| 国产精品爽爽久久| 久久综合久久综合九色| 中文字幕一区二区三区乱码| 国产污视频在线播放| 欧美日韩久久久一区| 大尺度做爰床戏呻吟舒畅| 日韩免费特黄一二三区| 久久久久亚洲精品| 国产精品毛片一区视频播| 99麻豆久久久国产精品免费优播| 亚洲一区二区在线看| 岛国av在线网站| 欧美一卡二卡三卡四卡| 国产高清一区二区三区四区| 亚洲视频在线免费| 国产精品看片资源| 亚洲 小说区 图片区 都市| 综合色天天鬼久久鬼色| 日本www.色| 日韩精品丝袜美腿| 久久久久久久久久亚洲| 国产精品丝袜黑色高跟鞋| 中文av一区特黄| 国产精品免费观看久久| 国产精品成人自拍| 欧美成人午夜影院| 一级特黄色大片| 国产日韩欧美综合一区| 欧美 国产 综合| 欧洲大片精品免费永久看nba| 国产亚洲人成a一在线v站| 免费看日韩毛片| 国产.欧美.日韩| 欧美精品国产精品久久久| 91精选在线| 91精品国产综合久久福利| 手机免费观看av| 蜜臀精品一区二区三区在线观看 | 国产精品二区二区三区| 国产三区在线观看| 欧美日韩久久久| 性爱在线免费视频| 美国毛片一区二区三区| 日韩片电影在线免费观看| 日韩免费小视频| 亚洲久久久久久久久久久| 综合激情网五月| ww亚洲ww在线观看国产| 国内精品在线观看视频| 国产精品22p| 国外色69视频在线观看| 亚洲狼人综合网| 精品久久久久久电影| 好吊一区二区三区视频| 亚洲欧美日韩一区在线观看| 日本一区二区三区视频在线观看| 电影亚洲精品噜噜在线观看| 在线观看日韩欧美| 中日精品一色哟哟| 成人免费一区二区三区视频| 亚洲色图偷拍视频| 综合久久亚洲| 国产精华一区二区三区| 1区2区在线观看| 亚洲成人久久一区| 欧美三级韩国三级日本三斤在线观看| 99久久精品国产精品久久| 国产淫片av片久久久久久| 日韩理论电影| 北条麻妃高清一区| 超碰aⅴ人人做人人爽欧美| 中文在线资源观看视频网站免费不卡| 波多野结衣一区二区在线| 国产精品区一区二区三区 | 99精品1区2区| 男人舔女人下面高潮视频| 色无极亚洲影院| 成人免费在线看片| 美女一区网站| 久久夜精品香蕉| 视频一区二区在线播放| 欧美吞精做爰啪啪高潮| 精品无码m3u8在线观看| 国产亚洲一本大道中文在线| 久久久九九九热| 亚洲欧美bt| 吴梦梦av在线| 色爱av综合网| 成人观看高清在线观看免费| 国精产品一区一区三区mba下载| 日韩精品免费在线视频| 91激情在线观看| 精品久久久中文| 内射一区二区三区| 久久久99久久| 人妻av一区二区三区| 日韩成人午夜精品| 国产一级做a爰片久久毛片男| 国产精选一区| 国产精品福利视频| 啪啪av大全导航福利综合导航| 久久欧美在线电影| 男女啪啪在线观看| 亚洲精品一区中文| 亚洲精品国产suv一区| 在线视频欧美精品| 99热国产在线观看| 亚洲一区二区三区自拍| 亚洲欧美精品久久| 久久久影视传媒| 无码国产69精品久久久久网站| 美女视频黄频大全不卡视频在线播放| 日韩av高清在线看片| 伊人情人综合网| 亚洲伊人婷婷| 国产欧美日韩影院| 久久久99爱| y111111国产精品久久久| 成人羞羞国产免费| 成人在线观看免费视频| 热久久美女精品天天吊色| 免费在线看电影| 欧美日本高清视频| 毛片在线播放a| 中文字幕精品—区二区| 欧洲亚洲在线| 国产丝袜一区二区三区| 动漫av一区二区三区| 日韩欧美三级在线| a在线观看免费| 欧美精品xxxxbbbb| 国产一区二区三区三州| 欧美日韩中文字幕一区二区| 中文字幕一区二区人妻视频| 日韩欧美一区视频| 日韩成人av毛片| 亚洲成人av电影在线| 国产亚洲第一页| 亚洲一区二区三区中文字幕| 手机在线免费看毛片| 亚洲三级免费电影| 欧美另类videoxo高潮| 中文字幕一区二区三区色视频| 国产美女免费网站| 国产日韩在线不卡| 男人天堂资源网| 国产精品天美传媒| 日韩亚洲欧美中文字幕| 一区精品在线播放| 成年人一级黄色片| 亚洲一区二区三区免费视频| 国产亚洲自拍av| 五月天久久比比资源色| 天天综合网久久综合网| 色噜噜狠狠成人网p站| 波多野结衣黄色| 欧美精三区欧美精三区| 国产成年妇视频| 精品国产一区二区亚洲人成毛片| 日本高清视频免费观看| 亚洲欧美日韩区| av在线播放网站| 久久中文字幕视频| 国产盗摄一区二区| 欧洲成人在线观看| 久久国产三级| 97人人模人人爽人人少妇| 久久久久高潮毛片免费全部播放| 免费看成人av| 久久综合电影| 17c丨国产丨精品视频| 一本色道久久综合亚洲精品高清| 女人喷潮完整视频| 美女网站色91| 性折磨bdsm欧美激情另类| 91在线小视频| 登山的目的在线| 精品久久久久久亚洲国产300| 久久久久久久久久成人| 在线不卡a资源高清| 国 产 黄 色 大 片| 亚洲日韩第一页| 91国内在线| 欧美最近摘花xxxx摘花| 四虎国产精品免费久久| 国产欧美日韩综合精品二区| 精品精品99| 国产精品国产三级国产专区51| 翔田千里一区二区| 999热精品视频| 久久久噜噜噜久噜久久综合| 国产性生活大片| 天天射综合影视| 国产乱码一区二区| 亚洲美女在线看| 蜜臀av在线播放| 国产精品视频yy9099| 久久男人av| 懂色av粉嫩av蜜臀av| 久久精品91| 日本少妇一级片| 国产精品免费av| 免费观看一区二区三区毛片 | 高清乱码毛片入口| 主播福利视频一区| 色在线免费观看| 91精品久久久久久久久久久久久久| 红杏一区二区三区| 午夜啪啪福利视频| 日本不卡一区二区三区| 成人性生活免费看| 亚洲蜜臀av乱码久久精品蜜桃| 久久精品久久久久久久| 亚洲国产精品va在线| 国产色在线观看| 国产日本欧美一区二区三区在线| 色橹橹欧美在线观看视频高清 | 欧美卡一卡二| 成人高清视频观看www| 欧美日韩性在线观看| 国内性生活视频| 91在线云播放| 日韩免费观看一区二区| 日韩欧美国产小视频| 麻豆av免费在线观看| 国产欧美一区二区白浆黑人| 国产一区二区三区网| 日本精品一区在线观看| 成人av资源在线| 久久精品国产亚洲av香蕉| 日韩一区二区三区精品视频| 日本电影全部在线观看网站视频 | 免费黄色片视频| 国产丝袜一区二区三区| 忘忧草在线影院两性视频| 精品国产一区二区三区麻豆免费观看完整版 | 希岛爱理一区二区三区av高清| 久久久久无码国产精品一区| 亚洲成人中文| 第四色在线视频| 激情成人中文字幕| 日韩av地址| 国产99久久精品一区二区永久免费| 亚洲v天堂v手机在线| 欧美牲交a欧美牲交aⅴ免费真| 2欧美一区二区三区在线观看视频| 国产午夜精品无码| 亚洲精品wwwww| 二区三区不卡| 日韩激情久久| 老司机免费视频一区二区| 精品少妇一区二区三区密爱| 欧美另类videos死尸| 国产不卡在线| 99影视tv| 夜夜嗨一区二区三区| 久久精品国产亚洲AV熟女| 欧美在线免费播放| 天堂中文а√在线| 99在线国产| 国产婷婷精品| 你懂得视频在线观看| 欧美精品电影在线播放| 女同视频在线观看| 精品一区二区三区国产| 日韩国产在线观看一区| 多男操一女视频| 精品国产精品一区二区夜夜嗨| 超碰资源在线| 亚洲成人一区二区三区| 国产一区美女在线| 国产69精品久久久久久久久久| 亚洲欧洲xxxx| 国产精品日韩精品在线播放 | av成人免费网站| 亚洲精品在线三区| 成人爱爱网址| 在线不卡日本| eeuss影院一区二区三区 | 日韩欧美一级片| 麻豆理论在线观看| 正在播放一区| 97久久久精品综合88久久| 欧美激情一区二区三区免费观看| 日韩在线观看免费av| 精品国内亚洲2022精品成人| 日本中文字幕高清| 亚洲电影中文字幕在线观看| 福利在线观看| 国产精品免费一区二区三区四区| 丝袜亚洲另类丝袜在线| 欧美精品一级片| 伊人成人开心激情综合网| 在这里有精品| 久久久久久久久久久久91| 亚洲成人精品一区二区| 在线国产91| 久久国产精品 国产精品| 国产曰批免费观看久久久|