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

InnoDB B-TREE 索引怎么定位一條記錄?

數(shù)據(jù)庫 MySQL
本文以 WHERE 條件能夠命中索引為前提,介紹查詢操作定位 WHERE 條件掃描區(qū)間的第一條記錄。

對于 SQL 語句的執(zhí)行來說,定位 B-TREE 索引中的一條記錄,是個舉足輕重的能力。

InnoDB 是基于索引組織數(shù)據(jù)的,更新、刪除操作都需要先去索引中找到具體的記錄。

插入操作也需要先找到記錄要插入到索引的哪個位置。

查詢語句的 WHERE 條件能夠命中索引時,也需要先找到 WHERE 條件對應(yīng)的掃描區(qū)間的第一條記錄,然后從這條記錄開始沿著索引頁內(nèi)記錄之間的單向鏈表、索引頁之間的雙向鏈表依次讀取后續(xù)的記錄。

通過以上簡短的介紹,定位 B-TREE 索引中的記錄的重要性就顯而易見了。

本文是 MySQL 8 的第一篇文章,也是查詢優(yōu)化器的開篇。希望通過本文的介紹,能為大家理解后續(xù)文章打下一些基礎(chǔ)。

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

正文

1、 概述

更新、刪除、查詢操作定位索引中的一條記錄,插入操作找到要插入的位置,過程基本上是一樣的,源碼中也是在同一個方法中實(shí)現(xiàn)。

本文以 WHERE 條件能夠命中索引為前提,介紹查詢操作定位 WHERE 條件掃描區(qū)間的第一條記錄。

定位記錄過程中進(jìn)行的二分法查找、順序查找,會涉及到索引頁的部分結(jié)構(gòu)。

接下來會先用 2 個小節(jié)分別介紹掃描區(qū)間、以及和定位記錄過程相關(guān)的索引頁的部分結(jié)構(gòu)。

2、什么是掃描區(qū)間?

掃描區(qū)間就是 WHERE 條件中,由字段、關(guān)系運(yùn)算符(>、>=、<、<=、=)組成的,用于限定需要掃描記錄的范圍。

這個一句話描述太抽象,我們展開細(xì)說。

掃描區(qū)間可以按照不同維度分類:

  • 按是否有界,可以分為有界區(qū)間、單側(cè)有界區(qū)間。
  • 按開閉,可以分為開區(qū)間、閉區(qū)間、半開半閉區(qū)間。
  • 特殊區(qū)間,單點(diǎn)區(qū)間。

有界區(qū)間

  • 開區(qū)間,例如:WHERE a > 100 AND a < 200,掃描區(qū)間為 (100, 200)。
  • 閉區(qū)間,例如:WHERE a >= 100 AND a <= 200,掃描區(qū)間為 [100, 200]。
  • 左開右閉區(qū)間,例如:WHERE a > 100 AND a <= 200,掃描區(qū)間為 (100, 200]。
  • 左閉右開區(qū)間,例如:WHERE a >= 100 AND a < 200,掃描區(qū)間為 [100, 200)。

單側(cè)有界區(qū)間

  • 有下界,左開區(qū)間,例如:WHERE a > 100,掃描區(qū)間為 (100, +∞)。
  • 有下界,左閉區(qū)間,例如:WHERE a >= 100,掃描區(qū)間為 [100, +∞)。
  • 有上界,右開區(qū)間,例如:WHERE a < 200,掃描區(qū)間為 (-∞, 200)。
  • 有上界,右閉區(qū)間,例如:WHERE a <= 200,掃描區(qū)間為 (-∞, 200]。

單點(diǎn)區(qū)間

  • 只有一個值的區(qū)間,例如:WHERE a = 100,掃描區(qū)間為 [100, 100]。

3、索引頁結(jié)構(gòu)

B-TREE 索引的根結(jié)點(diǎn)、內(nèi)結(jié)點(diǎn)、葉結(jié)點(diǎn),都是索引頁。

索引頁內(nèi)部結(jié)構(gòu)比較復(fù)雜,以后會有文章專門介紹整個索引頁的結(jié)構(gòu),接下來我們只介紹定位記錄需要用到的結(jié)構(gòu):偽記錄、記錄鏈表、槽(SLOT,也可以叫記錄分組)。

記錄鏈表

索引頁每條記錄的頭信息中,都有一個 2 字節(jié)的空間,保存著下一條記錄在當(dāng)前索引頁中的偏移量。

偏移量,是記錄的數(shù)據(jù)(不包含記錄頭信息)的第一個字節(jié)的地址,減去索引頁的第一個字節(jié)的地址得到的數(shù)字。

InnoDB 索引頁最大可以設(shè)置為 64K,2 字節(jié)就可以表示索引頁中任何一個字節(jié)的偏移量。

這個 2 字節(jié)的空間,叫作 next_record,通過 next_record 可以把索引頁中的記錄串起來形成一個單向鏈表。

從任何一條記錄開始,一直往后遍歷,都能到達(dá)當(dāng)前索引頁中的最后一條記錄。

偽記錄

偽記錄指的是索引頁中,不是由用戶插入,而是 InnoDB 偷偷插入的記錄。

不管索引頁中是否有用戶插入的記錄(用戶記錄),每個索引頁中都會有 2 條偽記錄:

  • infimum,索引頁中的第一條記錄。

索引頁中有用戶記錄時,infimum 的 next_record 指向第一條用戶記錄。

索引頁中沒有用戶記錄時,infimum 的 next_record 指向 supremum 記錄。

  • supremum,索引頁中的最后一條記錄。

槽(SLOT)

索引頁中的 槽 分為 3 種類型:

  • infimum 槽,只包含一條記錄,就是 infimum 偽記錄。
  • supremum 槽,包含 1 ~ 8 條記錄,最后一條是 supremum 偽記錄,其余的是用戶記錄。
  • 普通槽,包含 4 ~ 8 條用戶記錄。

每個槽占用 2 字節(jié),保存著該槽對應(yīng)的 N 條記錄中,最大的那條記錄在當(dāng)前索引頁中的偏移量。

最大記錄指的是槽中按照索引字段升序排序的最后一條記錄。

索引頁中的槽,存儲在索引頁的一個專門的區(qū)域,這個區(qū)域叫作頁目錄(Page Directory)。

頁目錄區(qū)域中的槽是按照倒序排序,并且是緊挨著存儲的,第一個槽的位置在最后,第二個槽的位置在倒數(shù)第二個,依此類推,最后一個槽的位置在第一個。

4、定位掃描區(qū)間的第一條記錄

(1)抽象過程描述

B+ 樹索引包含根結(jié)點(diǎn)、內(nèi)結(jié)點(diǎn)、葉結(jié)點(diǎn),在一棵 3 層的 B+ 樹中定位掃描區(qū)間的第一條記錄,大體流程如下:

  • 從根結(jié)點(diǎn)開始,確定記錄在哪個內(nèi)結(jié)點(diǎn)中。
  • 進(jìn)入內(nèi)結(jié)點(diǎn),確定記錄在哪個葉結(jié)點(diǎn)中。
  • 進(jìn)入葉結(jié)點(diǎn),確定記錄的位置。

隨著 B+ 樹的層級增多或減少,以上步驟也會相應(yīng)的增多或減少。

上述流程中的每一個步驟,內(nèi)部過程是一樣的,都需要先進(jìn)行二分法查找、再進(jìn)行順序查找。

最后,如果是根結(jié)點(diǎn)和內(nèi)結(jié)點(diǎn),就再進(jìn)入下一個步驟;如果是葉結(jié)點(diǎn),就沒有然后了。

二分法查找、順序查找過程如下:

第 1 步,通過二分法查找,確定記錄屬于哪個槽。

每個索引頁的頭信息中有一個 2 字節(jié)的區(qū)域,存放著當(dāng)前索引頁中有多少個槽,這個區(qū)域的名字叫作 PAGE_N_DIR_SLOTS。

讀取 PAGE_N_DIR_SLOTS 的值,得到槽的數(shù)量,然后減 1,計算出槽的最大序號:high = PAGE_N_DIR_SLOTS - 1,由此,我們就得到了二分法的初始狀態(tài)的上邊界。

初始狀態(tài)的下邊界,就是第一個槽(infimum 槽)的序號,low = 0。

二分法查找可能會進(jìn)行 0 ~ N 輪(N >= 1),每一輪查找,都會先通過 mid = (low + high) / 2 計算出中間位置。

然后,判斷要查找的記錄是在 low 區(qū)間(low ~ mid),還是在 high 區(qū)間(mid ~ high)。

最后,根據(jù)判斷結(jié)果,進(jìn)入 low 區(qū)間或 high 區(qū)間,查找范圍就縮小了一半,繼續(xù)進(jìn)行下一輪查找,依此類推,直到 low 和 high 的值不滿足循條件 high - low > 1,二分法查找結(jié)束。

這里的二分法,不僅要支持單點(diǎn)掃描區(qū)間,還要支持大于、大于等于、小于、小于等于這些范圍掃描區(qū)間,不能找到一條滿足掃描區(qū)間的記錄之后就馬上停下來,而是要等到 low 和 high 的值不滿足循環(huán)條件,才能結(jié)束二分法查找的過程。

二分法查找結(jié)束時,要查找的記錄總是屬于high 槽(上邊界 high 對應(yīng)的槽),low 槽 總是 high 槽的前一個槽。這對于第 2 步順序查找能夠順利的找到記錄在槽中的位置很關(guān)鍵。

第 2 步,確定記錄所在的槽之后,沿著每條記錄頭信息中的 next_record 順序查找,確定記錄在槽中的位置。

以二分法查找結(jié)束時的狀態(tài)為基礎(chǔ),繼續(xù)進(jìn)行順序查找。

從 low 槽的最大記錄開始,通過頭信息中的 next_record 讀取下一條記錄。

比較下一條記錄中索引字段值和掃描區(qū)間的字段值,判斷下一條記錄是不是掃描區(qū)間的第一條記錄。

如果是,順序查找過程結(jié)束。

如果不是,繼續(xù)讀取下一條記錄,并判斷是否是掃描區(qū)間的第一條記錄,依此類推,直到要讀取的下一條記錄是 high 槽中的最大記錄,查找過程結(jié)束。

接下來,我們通過一個例子來把上面描述的抽象過程具體化。

(2)準(zhǔn)備一棵 B+ 樹

有一個主鍵索引,包含一個 int 類型的 id 字段,結(jié)構(gòu)為 B+ 樹,包含 2 層:根結(jié)點(diǎn)、葉結(jié)點(diǎn),索引結(jié)構(gòu)如下圖所示:

我們以定位 id >= 700 查詢條件對應(yīng)的掃描區(qū)間 [700, +∞) 的第一條記錄為例,來分析在 B+ 樹索引中定位掃描區(qū)間的第一條記錄的過程。

(3)記錄在哪個葉結(jié)點(diǎn)?

示例索引的 B+ 樹,包含根結(jié)點(diǎn)、葉結(jié)點(diǎn)兩層,定位掃描區(qū)間的第一條記錄,從根結(jié)點(diǎn)開始。

根據(jù)抽象過程描述的步驟,先通過二分法查找確定 [700, +∞) 掃描區(qū)間的第一條記錄在哪個槽。

示例索引的 B+ 樹,根結(jié)點(diǎn)中有 8 個槽,初始狀態(tài)下,二分法的上下邊界分別為:low = 0、high = 8 - 1 = 7。

二分法查找

第 1 輪,計算中間位置 mid = (low + high) / 2 = (0 + 7) / 2 = 3,得到 low 區(qū)間(low ~ mid => 0 ~ 3)、high 區(qū)間(mid ~ high => 3 ~ 7)。

中間位置對應(yīng)槽 3(序號為 3 的槽),其最大記錄的 id = 41,小于掃描區(qū)間左端點(diǎn)值 700,說明 id >= 700 的第一條記錄(后面就直接稱為第一條記錄了)位于 high 區(qū)間。

修改下邊界值,low = mid = 3,進(jìn)入 high 區(qū)間。

第 2 輪,計算中間位置 mid = (low + high) / 2 = (3 + 7) / 2 = 5,得到 low 區(qū)間(3 ~ 5)、high 區(qū)間(5 ~ 7)。

中間位置對應(yīng)槽 5,其最大記錄的 id = 81,小于掃描區(qū)間左端點(diǎn)值 700,說明第一條記錄位于 high 區(qū)間。

修改下邊界值,low = mid = 5,進(jìn)入 high 區(qū)間。

第 3 輪,計算中間位置 mid = (low + high) / 2 = (5 + 7) / 2 = 6,得到 low 區(qū)間(5 ~ 6)、high 區(qū)間(6 ~ 7)。

中間位置對應(yīng)槽 6,其最大記錄的 id = 901,大于掃描區(qū)間左端點(diǎn)值 700,說明第一條記錄位于 low 區(qū)間。

修改上邊界值,high = mid = 6。

然后,high - low = 6 - 5 = 1,不滿足循環(huán)條件 high - low > 1,二分法查找結(jié)束。

掃描區(qū)間左端點(diǎn)值 700,大于槽 5的最大記錄的 id 值(81),小于槽 6的最大記錄的 id 值(901),說明第一條記錄屬于槽 6 的管轄范圍(此時,槽 6 就是 high 槽)。

接下來,就要進(jìn)入順序查找的主場,去尋找第一條記錄在槽中的位置了。

順序查找

二分法查找結(jié)束時,low = 5(槽 5),其最大記錄的 id = 81;high = 6(槽 6),其最大記錄的 id = 901。

二分法查找過程中,已經(jīng)確定了掃描區(qū)間左端點(diǎn)值 700 在槽 6中,所以,在順序查找過程中,不需要讀取 id = 81 這條記錄(槽 5的最后一條記錄),而是從這條記錄的下一條記錄,也就是槽 6 的第一條記錄開始。

第 1 輪,讀取 id = 81 的下一條記錄,得到 id = 101 的記錄,101 小于掃描區(qū)間左端點(diǎn)值 700,還需要繼續(xù)讀取下一條記錄進(jìn)行比較。

第 2 輪,讀取 id = 101 的下一條記錄,得到 id = 888 的記錄,888 大于掃描區(qū)間左端點(diǎn)值 700,也就鎖定了 id >= 700 的第一條記錄,位于 id 為 101 ~ 888 的記錄之間,也就是在 id = 888 之前。

然而,id = 888 這條記錄,是其所在的葉結(jié)點(diǎn)索引頁的第一條用戶記錄。

id >= 700 的第一條記錄,不可能和 id = 888 這條記錄同處于一個索引頁了,只能立足于這個索引頁的前一個索引頁。

根結(jié)點(diǎn)中 id = 101 是 id = 888 的前一條記錄,id = 101 所在的葉結(jié)點(diǎn)索引頁就是 id = 888 所在的葉結(jié)點(diǎn)索引頁的前一頁了。

最終,id >= 700 的第一條記錄,也就位于 id = 101 這條記錄所在的葉結(jié)點(diǎn)索引頁中了。

至此,經(jīng)過 2 輪比較,就已經(jīng)確定了 id >= 700 的第一條記錄所在的葉結(jié)點(diǎn)索引頁了,順序查找過程結(jié)束。

接下來,從 id = 101 這條記錄中讀取其對應(yīng)的葉結(jié)點(diǎn)索引頁的頁號,進(jìn)入葉結(jié)點(diǎn)。

(4)記錄在葉結(jié)點(diǎn)的哪個位置?

示例索引的 B+ 樹,葉結(jié)點(diǎn)中有 10 個槽,初始化狀態(tài)下,二分法查找的上下邊界分別為:low = 0,high = 10 - 1 = 9。

二分法查找

第 1 輪,計算中間位置 mid = (low + high) / 2 = (0 + 9) / 2 = 4,得到 low 區(qū)間(low ~ mid => 0 ~ 4)、high 區(qū)間(mid ~ high => 4 ~ 9)。

中間位置對應(yīng)槽 4,其最大記錄的 id = 404,小于掃描區(qū)間左端點(diǎn)值 700,說明 id >= 700 的第一條記錄(簡稱為第一條記錄)位于 high 區(qū)間。

修改下邊界值,low = mid = 4,進(jìn)入 high 區(qū)間。

第 2 輪,計算中間位置 mid = (low + high) / 2 = (4 + 9) / 2 = 6,得到 low 區(qū)間(4 ~ 6)、high 區(qū)間(6 ~ 9)。

中間位置對應(yīng)槽 6,其最大記錄的 id = 606,小于掃描區(qū)間左端點(diǎn)值 700,說明第一條記錄位于 high 區(qū)間。

修改下邊界值,low = mid = 6,進(jìn)入 high 區(qū)間。

第 3 輪,計算中間位置 mid = (low + high) / 2 = (6 + 9) / 2 = 7,得到 low 區(qū)間(6 ~ 7)、high 區(qū)間(7 ~ 9)。

中間位置對應(yīng)槽 7,其最大記錄的 id = 707,大于掃描區(qū)間左端點(diǎn)值 700,說明第一條記錄位于 low 區(qū)間。

修改上邊界值,up = mid = 7,此時,high - low = 7 - 6 = 1,不滿足循環(huán)條件 up - low > 1,循環(huán)結(jié)束。

掃描區(qū)間左端點(diǎn)值 700,大于槽 6 的最大記錄的 id(606),小于槽 7 的最大記錄的 id(707),說明第一條記錄屬于槽 7 的管轄范圍(此時,槽 7就是 high 槽)。

接下來,就要去尋找第一條記錄在槽中的位置了。

順序查找

二分法查找結(jié)束時,low = 6(槽 6),其最大記錄的 id = 606;high = 7(槽 7),其最大記錄的 id = 707。

二分法查找過程中,已經(jīng)確定了第一條記錄在槽 7 的范圍內(nèi),所以,在順序查找過程中,不需要讀取 id = 606 這條記錄(槽 6 的最后一條記錄),而是從這條記錄的下一條記錄,也就是槽 7 的第一條記錄開始。

第 1 輪,讀取 id = 606 的下一條記錄,得到 id = 666 的記錄,666 小于掃描區(qū)間左端點(diǎn)值 700,還需要讀取下一條記錄進(jìn)行比較。

第 2 輪,讀取 id = 666 的下一條記錄,得到 id = 688 的記錄,688 小于掃描區(qū)間左端點(diǎn)值 700,繼續(xù)讀取下一條記錄。

第 3 輪,讀取 id = 688 的下一條記錄,得到 id = 700 的記錄,700 等于掃描區(qū)間左端點(diǎn)值 700, 滿足 id >= 700 條件。

至此,經(jīng)過 3 輪比較,已找到 id >= 700 對應(yīng)的掃描區(qū)間 [700, +∞) 的第一條記錄,葉結(jié)點(diǎn)的順序查找過程結(jié)束,定位掃描區(qū)間的第一條記錄的整個過程也結(jié)束了。

5、 性能優(yōu)化

前面介紹二分法查找定位槽、順序查找定位記錄位置的過程中,都涉及到對掃描區(qū)間字段值和索引字段值進(jìn)行比較,但是我們沒有更進(jìn)一步介紹比較的過程。

如果只是常規(guī)的比較,無非是循環(huán)掃描區(qū)間的字段,逐個和索引中對應(yīng)的字段進(jìn)行比較,這也就不需要再多說什么了。

但是,InnoDB 對比較的過程進(jìn)行了優(yōu)化,對于已經(jīng)比較過的字段、字段前面的部分內(nèi)容,盡可能避免進(jìn)行重復(fù)比較,從而提升二分法查找、順序查找過程的執(zhí)行效率,以提升性能。

InnoDB 對于葉結(jié)點(diǎn)的優(yōu)化相比于根結(jié)點(diǎn)、內(nèi)結(jié)點(diǎn)來說更進(jìn)一步,我們分兩個小節(jié)分別介紹對于根結(jié)點(diǎn) & 內(nèi)結(jié)點(diǎn)、葉結(jié)點(diǎn)的二分法查找、順序查找的優(yōu)化。

(1)根結(jié)點(diǎn)、內(nèi)結(jié)點(diǎn)優(yōu)化

我們基于上圖索引頁中槽的示例數(shù)據(jù),以查詢條件 i1 >= 160 and i2 >= 44 為例,來分析定位掃描區(qū)間左端點(diǎn) 160, 44(用這個代表掃描區(qū)間的第一條記錄) 在哪個槽中的過程。

初始狀態(tài)下,二分法查找的上下邊界為:low = 0,high = 13。

二分法查找

第 1 輪,計算中間位置 mid = (low + high) / 2 = (0 + 13) / 2 = 6,得到 low 區(qū)間(low ~ mid => 0 ~ 6)、high 區(qū)間(mid ~ high => 6 ~ 13)。

中間位置對應(yīng)槽 6,其最大記錄的 i1 = 160、i2 = 33,逐個比較掃描區(qū)間左端點(diǎn)和槽 6 的最大記錄的 i1、i2 字段值,以確定掃描區(qū)間左端點(diǎn)位于 low 區(qū)間還是 high 區(qū)間。

先比較 i1 字段值,掃描區(qū)間左端點(diǎn)的 i1 字段值和索引中的 i1 字段值都等于 160。

接著比較 i2 字段的值,掃描區(qū)間左端點(diǎn)的 i2 字段值(44)大于索引記錄中的 i2 字段值(33),說明掃描區(qū)間左端點(diǎn)值 160, 44 位于 high 區(qū)間(槽 6 ~ 13)。

修改下邊界值,low = mid = 6,進(jìn)入 high 區(qū)間。

第 2 輪,計算中間位置 mid = (low + high) / 2 = (6 + 13) / 2 = 9,得到 low 區(qū)間(6 ~ 9)、high 區(qū)間(9 ~ 13)。

中間位置對應(yīng)槽 9,其最大記錄的 i1 = 160,i2 = 66,逐個比較掃描區(qū)間左端點(diǎn)和槽 9 的最大記錄的 i1、i2 字段值,以確定掃描區(qū)間左端點(diǎn)位于 low 區(qū)間還是 high 區(qū)間。

先比較 i1 字段值,掃描區(qū)間左端點(diǎn)的 i1 字段值和索引記錄中的 i1 字段值都等于 160。

接著比較 i2 字段的值,掃描區(qū)間左端點(diǎn)的 i2 字段值(44)小于索引記錄中的 i2 字段值(66),說明掃描區(qū)間左端點(diǎn)值 160, 44 位于 low 區(qū)間(槽 6 ~ 9)。

修改上邊界值,high = mid = 9,進(jìn)入 low 區(qū)間。

第 3 輪,計算中間位置 mid = (low + high) / 2 = (6 + 9) / 2 = 7,得到 low 區(qū)間(6 ~ 7)、high 區(qū)間(7 ~ 9)。

中間位置對應(yīng)槽 7,其最大記錄的 i1 = 160,i2 = 44。

按照第 1、2 輪的套路,接下來該逐個比較掃描區(qū)間左端點(diǎn)和槽 7 的最大記錄的 i1、i2 字段值了。

但是 ……,重點(diǎn)來了,經(jīng)過第 1 輪比較,確定了掃描區(qū)間左端點(diǎn)值 160, 44 位于槽 6 ~ 13 之間;經(jīng)過第 2 輪比較,確定了掃描區(qū)間左端點(diǎn)值 160, 44 位于槽 6 ~ 9 之間。

取交集可得:掃描區(qū)間左端點(diǎn)值 160, 44 位于槽 6 ~ 9 之間。

從前面的示意圖中可見,槽 6 ~ 9 之間,每個槽的最大記錄的 i1 字段值都是 160,掃描區(qū)間左端點(diǎn)的 i1 字段值也是 160。

在這個范圍內(nèi),不管接下來要進(jìn)行多少輪比較,都能夠很確定的知道記錄的 i1 字段值是等于掃描區(qū)間左端點(diǎn)的 i1 字段值的。

既然在比較之前就已經(jīng)能確定比較的結(jié)果是相等的,也就不用比較了 i1 字段的值了。

二分法查找結(jié)束之后,后面的順序查找過程,也是在這個范圍之內(nèi),也都可以不用比較 i1 字段的值了。

好了,這一節(jié)我們要講的是 InnoDB 對定位過程的優(yōu)化,目標(biāo)已經(jīng)達(dá)成,對于上面的例子,剩下的二分法查找和順序查找過程,就不再接著往下分析了。

(2)葉結(jié)點(diǎn)優(yōu)化

如果能夠在二分法查找過程中鎖定一個范圍,葉結(jié)點(diǎn)的二分法查找、順序查找過程,不但能跳過前面 N 個已經(jīng)比較過并且相等的字段,還能更進(jìn)一步,跳過第 N + 1 個字段中已經(jīng)比較過并且相等的前 M 字節(jié)。

不過,跳過已經(jīng)比較過的字節(jié)有一些限制,只能應(yīng)用于以下字段:

  • tinyint、int、smallint、mediumint、bigint、tinyblob、blob、mediumblob、longblob、binary、varbinary 類型的字段。
  • InnoDB B-TREE 根結(jié)點(diǎn)、內(nèi)結(jié)點(diǎn)的記錄中指向子結(jié)點(diǎn)索引頁的頁號。
  • InnoDB B-TREE 葉結(jié)點(diǎn)記錄中的 DB_ROW_ID、DB_TRX_ID、DB_ROLL_PTR 字段。

以上這些類型的字段,在二分法查找和順序查找的過程中,源碼中是要循環(huán)字段內(nèi)容,逐字節(jié)進(jìn)行比較的。

我們還是以一個具體例子來說明:

有一個 B-TREE 索引,包含 2 個字段,i1 為 int 類型,b1 為 blob 類型,如下圖所示:

假設(shè)掃描區(qū)間左端點(diǎn)的 i1 字段值為 160,b1 字段值的前 1000 字節(jié)為 0x001 0x002 … 0x999 0x1000。

再次假設(shè),經(jīng)過前 2 輪比較已經(jīng)鎖定了掃描區(qū)間的左端點(diǎn)值在 槽 6 ~ 槽 9 之間,這個區(qū)間內(nèi)所有記錄的 i1 字段值都是 160,所有記錄的 b1 字段前 1000 字節(jié)都是 0x001 0x002 … 0x999 0x1000。

如果在第 3 輪及以后的二分法查找、順序查找過程中,只能跳過已經(jīng)比較過的 i1 字段,對于 b1 字段,每次都要從第 1 個字節(jié)開始比較,前 1000 字節(jié)的逐字節(jié)比較就重復(fù)了。

按照我們前面介紹的場景,在鎖定范圍內(nèi)(槽 6 ~ 9),掃描區(qū)間左端點(diǎn)的 i1 字段和所有記錄的 i1 字段值都相等;b1 字段前 1000 字節(jié)也都相等,也不用比較,是可以跳過的。

那么,在二分法查找的后續(xù)比較、順序查找過程中,只需要從 b1 字段的第 1001 字節(jié)開始比較,又能更多的避免一些重復(fù)的比較操作了。

6、總結(jié)

正式進(jìn)入本文主題內(nèi)容之前,2、3 小節(jié)先介紹了掃描區(qū)間的定義,以及舉例說明了每種類型的掃描區(qū)間;然后介紹了索引頁中和本文關(guān)聯(lián)比較大的結(jié)構(gòu):記錄鏈表、偽記錄、槽(SLOT)。

4 小節(jié)先對二分法查找定位槽、順序查找定位槽中的記錄進(jìn)行抽象的過程描述,然后,以一個 2 層的 B-TREE 索引為例,詳細(xì)分析了二分法查找定位槽、順序查找定位槽中記錄的每一步。

5 小節(jié)介紹了 InnoDB 為了減少二分法查找定位槽、順序查找定位槽中記錄的過程中的比較次數(shù),在鎖定一個范圍之后,對于根結(jié)點(diǎn)、內(nèi)結(jié)點(diǎn),能夠跳過已經(jīng)比較過并確認(rèn)為相等的字段;對于葉結(jié)點(diǎn),除了能跳過字段,還能跳過字段中已經(jīng)比較過并確認(rèn)為相等的前面的部分字節(jié)。

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

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

2022-05-30 08:01:36

WHEREMySQL索引

2010-10-12 16:50:14

MySQL Hash索

2023-01-26 00:59:39

B-Treegolang度量衡

2024-02-27 07:35:55

B-TreeB+TreeMySQL

2018-08-26 06:24:58

MySQLInnoDB行鎖

2023-01-30 23:04:10

B-Treegolang優(yōu)化

2025-06-16 07:45:00

2011-05-12 14:43:57

MYSQL

2024-09-04 08:44:18

MySQL核心模塊

2024-04-19 07:31:58

MySQL數(shù)據(jù)庫

2021-09-12 07:26:49

MySQL SQL 語句數(shù)據(jù)庫

2022-10-29 08:44:39

分布式數(shù)據(jù)庫存儲

2025-05-28 01:10:00

SQL索引MySQL

2021-09-28 13:32:24

innoDB架構(gòu)MySQL

2015-07-28 11:06:28

日志記錄Linux命令

2024-05-22 09:01:53

InnoDBB+索引

2010-04-13 16:57:01

2011-08-17 09:13:08

MySQL數(shù)據(jù)庫多條記錄的單個字段

2020-07-15 09:29:23

Python開發(fā)工具

2010-11-15 14:16:09

Oracle表記錄
點(diǎn)贊
收藏

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

午夜国产精品影院在线观看| 一本色道久久综合| 欧美三级在线看| 亚洲第一导航| 国产又黄又粗又长| 亚洲欧美亚洲| 亚洲精品福利在线观看| 乱子伦视频在线看| 欧美激情免费| 福利一区二区在线| 热久久免费国产视频| 男人舔女人下部高潮全视频| 国产成人精品一区二区三区视频 | 国产91对白在线播放| 乐播av一区二区三区| 日韩精品一页| 亚洲欧美日韩综合aⅴ视频| 91色精品视频在线| 亚洲精品www久久久久久| av亚洲在线观看| 欧洲av在线精品| 91制片厂免费观看| 色一情一乱一乱一区91av| 免费在线欧美黄色| 三级精品视频久久久久| 黄页网站在线看| 亚洲天堂资源| 亚洲天堂成人在线观看| 久久99国产精品99久久| 中文字幕日韩经典| 亚洲精品字幕| 日韩一区二区久久久| 韩国三级在线看| 欧美va在线观看| 一区二区成人在线视频| 青青成人在线| 成人久久精品人妻一区二区三区| 视频在线观看一区二区三区| 久久综合伊人77777| 新91视频在线观看| 国产一区二区三区精品在线观看| 色综合欧美在线| 国产aaa免费视频| 日本最新在线视频| 91麻豆国产香蕉久久精品| 川上优av一区二区线观看| 天天操夜夜操视频| 国模吧视频一区| 深夜精品寂寞黄网站在线观看| 国产精品福利导航| 视频精品国内| 欧美日韩成人综合| 国产精品久久中文字幕| 川上优的av在线一区二区| 成人性色生活片| 91性高湖久久久久久久久_久久99| 无码免费一区二区三区| 亚洲日韩视频| 九九九热精品免费视频观看网站| 五月天婷婷丁香网| 日韩理论电影中文字幕| 日韩你懂的在线播放| 三上悠亚av一区二区三区| 电影一区二区三区| 精品久久久久久久久久久久久久| 男人天堂新网址| 久久久久久久久免费视频| 国产欧美一区二区精品性色超碰| 激情伦成人综合小说| 国产三级视频在线播放| 久久99国产精品免费| 国产999视频| 日韩 国产 欧美| 丝袜美腿亚洲综合| 国产精品69久久| 久久久久99精品成人片三人毛片| 亚洲人www| 97精品国产97久久久久久| 久久精品视频日本| 一区二区三区福利| 97在线精品视频| 国产日产精品一区二区三区| 国产精品亚洲欧美| 国产va免费精品高清在线| 日韩欧美亚洲国产| 国产精品日韩久久久| 茄子视频成人在线| 欧美性受xxx黑人xyx性爽| 日韩电影在线免费看| 国产欧美精品一区二区三区-老狼| 天堂av免费在线观看| 美女视频一区免费观看| 国产福利视频一区| 一区不卡在线观看| 国产一区二区三区在线看麻豆| 亚洲综合在线小说| 日日躁夜夜躁白天躁晚上躁91| 成人中文字幕合集| 欧美在线3区| 欧美日韩视频在线播放| 亚洲你懂的在线视频| 日韩网站在线免费观看| 亚洲同志男男gay1069网站| 欧美色综合天天久久综合精品| 99草草国产熟女视频在线| 免费一区二区三区四区| 91精品国产高清一区二区三区蜜臀| 色综合久久久无码中文字幕波多| 美女一区二区在线观看| 中文字幕精品网| 色偷偷www8888| 亚洲国产导航| 国产精品a久久久久久| 一区二区不卡视频在线观看| 岛国精品在线播放| 日本10禁啪啪无遮挡免费一区二区| 在线看av的网址| 亚洲一级不卡视频| 日本美女高潮视频| 日韩欧美中文字幕在线视频 | 人妻视频一区二区三区| 国产精品无人区| 日本一本中文字幕| 亚洲香蕉久久| 亚洲欧美一区二区三区久久| 无码人妻精品中文字幕| 亚洲大胆在线| 国产区精品在线观看| 色呦呦视频在线| 中文字幕人成不卡一区| 99999精品视频| 久久三级中文| 一区二区三区视频免费在线观看| 免费中文字幕视频| 麻豆91精品91久久久的内涵| 狠狠干一区二区| 在线视频91p| 欧美丝袜第一区| 苍井空张开腿实干12次| 欧美一级精品片在线看| 7777精品久久久久久| www.日韩在线观看| 久久精品视频在线免费观看| 黄色激情在线视频| 成人久久精品| 尤物yw午夜国产精品视频明星| 天天插天天操天天干| 国产成人免费网站| 国产大尺度在线观看| 美女写真久久影院| 日韩精品久久久久久福利| 免费看一级一片| 国产在线精品一区在线观看麻豆| 日韩美女一区| 免费亚洲电影| 亚洲精品一区二区三区婷婷月| 久久综合激情网| 九九精品视频在线看| 日本一区二区久久精品| 免费影视亚洲| 日韩精品专区在线| 欧美三级 欧美一级| 国产在线精品国自产拍免费| 午夜精品视频在线观看一区二区| 桃子视频成人app| 日韩精品在线观| 超碰超碰超碰超碰| wwwwxxxxx欧美| 秋霞无码一区二区| 日本欧美高清| 秋霞成人午夜鲁丝一区二区三区| 丰满人妻一区二区三区无码av| 一区二区三区影院| 蜜桃视频无码区在线观看| 午夜亚洲福利| 国产欧美日韩一区| 污视频在线免费观看网站| 日韩欧美资源站| 久久97人妻无码一区二区三区| 国内不卡的二区三区中文字幕| 国产四区在线观看| 538任你躁精品视频网免费| 久久精品成人欧美大片古装| 国产人妖一区二区| 一区二区三区在线不卡| 亚洲一级Av无码毛片久久精品| 在线精品观看| 九色91国产| 欧美成人影院| 最近中文字幕2019免费| 国产三级漂亮女教师| 亚洲一区二区三区视频在线播放| 国产美女视频免费观看下载软件| 亚洲精品社区| 日韩欧美三级一区二区| 亚洲男人在线| 久久久久久久爱| 男同在线观看| 欧美午夜理伦三级在线观看| 日韩精品一区二区三区在线视频| 九九九久久久精品| 精品国偷自产一区二区三区| 日韩深夜福利| 成人激情在线观看| av在线最新| 日韩视频在线免费观看| 亚洲AV无码成人片在线观看 | 亚洲美女喷白浆| 一区二区视频网站| 一区二区在线看| 亚洲精品无码一区二区| 三级亚洲高清视频| 一本色道久久88亚洲精品综合| 精品久久ai电影| 国产精品视频久久| 羞羞的视频在线看| 亚洲第一在线视频| 亚洲无码精品在线播放| 性做久久久久久免费观看| 国产又黄又粗的视频| 激情图片小说一区| 男人揉女人奶房视频60分| 久久中文字幕av| 精品国产二区在线| 伊人久久一区| 秋霞午夜一区二区| 午夜小视频在线观看| 国产小视频91| 天天操天天操天天干| 91精品免费在线| 成年人视频免费| 亚洲图片有声小说| 日韩a级片在线观看| 久久男人中文字幕资源站| 久草福利在线观看| 蜜桃传媒麻豆第一区在线观看| 亚洲人成无码网站久久99热国产| 色婷婷色综合| 欧美久久久久久一卡四| ccyy激情综合| 成人在线国产精品| 秋霞国产精品| 浅井舞香一区二区| 欧美sm一区| 欧美激情精品久久久久久| 天堂а√在线官网| 中文国产亚洲喷潮| 国产免费a∨片在线观看不卡| 亚洲精品av在线| 亚洲精品久久久久久久久久| 在线不卡一区二区| 一本色道久久综合无码人妻| 在线免费观看日韩欧美| 日本一区二区三区精品| 亚洲国产精品人人做人人爽| 国产第一页浮力| 中文字幕在线不卡国产视频| 亚洲区自拍偷拍| 久久亚洲精华国产精华液 | 国产精品一区二区av影院萌芽| 午夜精品视频在线| 日本不良网站在线观看| 久久久久在线观看| 大香伊人中文字幕精品| 久久久免费在线观看| 久操av在线| 国内精品久久久久久久久| sm在线观看| 51精品国产黑色丝袜高跟鞋| 蜜桃麻豆影像在线观看| 久久久久久成人| 国产精品论坛| 欧美一级在线亚洲天堂| 在线天堂中文资源最新版| 国产69久久精品成人看| 欧美一区久久久| 国产精品久久久久久久av电影| 秋霞国产精品| 国产精品男人的天堂| 香蕉久久一区| 97se在线视频| 激情亚洲另类图片区小说区| 国产精品区一区二区三含羞草| 你懂的在线观看一区二区| 六月婷婷久久| 日韩理论在线| 在线电影看在线一区二区三区| 99久久精品网| 黄色一级大片免费| 天堂影院一区二区| 香蕉网在线视频| 26uuu精品一区二区在线观看| 国产精成人品免费观看| 亚洲欧美电影院| 国产无遮挡呻吟娇喘视频| 51精品视频一区二区三区| 免费成人在线看| 中文字幕亚洲欧美| 男人添女人下部高潮视频在线观看| 日本一区二区在线播放| 国产日本亚洲| 日本一区二区三不卡| 欧美日韩国产亚洲一区| 男女无套免费视频网站动漫| 国产91精品一区二区麻豆亚洲| 午夜精产品一区二区在线观看的| 亚洲另类在线制服丝袜| 国产又粗又猛又黄视频| 精品国产乱码久久久久久久久| 成人亚洲综合天堂| 久久久爽爽爽美女图片| 日日夜夜亚洲| 欧美三级华人主播| 亚洲三级视频| 久久精品一二三四| 国产精品美日韩| 黄色在线免费观看| 欧美成人性战久久| 自拍视频在线网| 国产成人极品视频| 欧美绝顶高潮抽搐喷水合集| 色一情一乱一乱一区91| 日韩**一区毛片| 噜噜噜在线视频| 亚洲一区二区影院| 国产美女三级无套内谢| 中文字幕欧美专区| 桃色一区二区| 美日韩精品免费| 日韩午夜电影| 日韩成人av影院| 亚洲美女偷拍久久| 91中文字幕在线视频| 精品调教chinesegay| 9999精品成人免费毛片在线看| 亚洲最大成人网色| 亚洲天天影视网| 中国黄色片一级| 中文字幕av一区二区三区| 国产寡妇亲子伦一区二区三区四区| 精品播放一区二区| a级大胆欧美人体大胆666| 99久久99久久精品国产片| 欧美一区视频| 4438x全国最大成人| 亚洲免费看黄网站| a网站在线观看| 欧美成人中文字幕| 精品一区二区三区四区五区| 吴梦梦av在线| 国产伦精品一区二区三区视频青涩 | 欧美视频在线视频精品| 亚洲精品9999| 久久国产精品区| 秋霞欧美一区二区三区视频免费| 在线不卡一区二区| av在线免费播放| 99电影在线观看| 在线播放一区| 日本丰满少妇裸体自慰| 色综合久久中文字幕综合网| 国产黄在线看| 成人信息集中地欧美| 午夜国产欧美理论在线播放| 日本wwwwwww| 欧美日韩国产中文字幕| 久久这里精品| 国产日本欧美一区| 欧美视频久久| 亚洲国产精品成人综合久久久| 色先锋资源久久综合| h网站在线免费观看| 91色精品视频在线| 在线日本高清免费不卡| 欧美特黄一区二区三区| 欧美日韩一区二区三区免费看| 国产色在线观看| 国产91精品一区二区绿帽| 夜夜爽av福利精品导航| 三区四区在线观看| 欧美va天堂va视频va在线| 免费成人在线电影| 亚洲精品成人久久久998| 国产精品99久久久久久似苏梦涵 | 亚洲一级高清| 亚洲区自拍偷拍| 日韩欧美国产一二三区| 欧美gv在线| 手机在线视频你懂的| av网站一区二区三区| 在线观看黄色国产| 欧美激情奇米色| 国产综合久久久| 丰满人妻一区二区三区大胸| 日韩欧美高清在线视频| 国产精品扒开做爽爽爽的视频| 美女三级99| 国产福利91精品一区二区三区| 国产免费一级视频| 欧美裸体xxxx极品少妇|