聯合索引在B 樹上的儲存結構及資料查詢方式

2022-09-17 21:15:21 字數 2927 閱讀 9318

下面就引用思否社群的這個問答來展開我們今天要討論的聯合索引的儲存結構的問題。

來自思否的提問,聯合索引的儲存結構(有碼友回答如下:

聯合索引 bcd , 在索引樹中的樣子如圖 , 在比較的過程中 ,先判斷 b 再判斷 c 然後是 d ,

由於回答只有一張圖一句話,可能會讓你有點看不懂,所以我們就借助前人的肩膀用這個例子來更加細緻的講探尋一下聯合索引在b+樹上的儲存結構吧。

首先,表t1有欄位a,b,c,d,e,其中a是主鍵,除e為varchar其餘為int型別,並建立了乙個聯合索引idx_t1_bcd(b,c,d),然後b、c、d三列作為聯合索引,在b+樹上的結構正如上圖所示。聯合索引的所有索引列都出現在索引數上,並依次比較三列的大小。上圖樹高只有兩層不容易理解,下面是假設的表資料以及我對其聯合索引在b+樹上的結構圖的改進。ps:基於innodb儲存引擎。

bcd聯合索引在b+樹上的結構圖

通過這倆圖我們心裡對聯合索引在b+樹上的儲存結構就有了個大概的認識。下面用我的語言為大家解釋一下吧。

我們先看t1表,他的主鍵暫且我們將它設為整型自增的(ps:至於為什麼是整型自增上篇文章有詳細介紹這裡不再多說),innodb會使用主鍵索引在b+樹維護索引和資料檔案,然後我們建立了乙個聯合索引(b,c,d)也會生成乙個索引樹,同樣是b+樹的結構,只不過它的data部分儲存的是聯合索引所在行的主鍵值(上圖葉子節點紫色背景部分),至於為什麼輔助索引data部分儲存主鍵值上篇文章也有介紹,感興趣或還不知道的可以去看一下。

好了大致情況都介紹完了。下面我們結合這倆圖來解釋一下。

對於聯合索引來說只不過比單值索引多了幾列,而這些索引列全都出現在索引樹上。對於聯合索引,儲存引擎會首先根據第乙個索引列排序,如上圖我們可以單看第乙個索引列,如,1 1 5 12 13....他是單調遞增的;如果第一列相等則再根據第二列排序,依次類推就構成了上圖的索引樹,上圖中的1 1 4 ,1 1 5以及13 12 4,13 16 1,13 16 5就可以說明這種情況。

當我們的sql語言可以應用到索引的時候,比如select * from t1 where b = 12 and c = 14 and d = 3;也就是t1表中a列為4的這條記錄。

儲存引擎首先從根節點(一般常駐記憶體)開始查詢,第乙個索引的第乙個索引列為1,12大於1,第二個索引的第乙個索引列為56,12小於56,於是從這倆索引的中間讀到下乙個節點的磁碟檔案位址,從磁碟上load這個節點,通常伴隨一次磁碟io,然後在記憶體裡去查詢。

當load葉子節點的第二個節點時又是一次磁碟io,比較第乙個元素,b=12,c=14,d=3完全符合,於是找到該索引下的data元素即id值,再從主鍵索引樹上找到最終資料。

之所以會有最左字首匹配原則和聯合索引的索引構建方式及儲存結構是有關係的。

首先我們建立的idx_t1_bcd(b,c,d)索引,相當於建立了(b)、(b、c)(b、c、d)三個索引,看完下面你就知道為什麼相當於建立了三個索引。

我們看,聯合索引是首先使用多列索引的第一列構建的索引樹,用上面idx_t1_bcd(b,c,d)的例子就是優先使用b列構建,當b列值相等時再以c列排序,若c列的值也相等則以d列排序。我們可以取出索引樹的葉子節點看一下。

索引的第一列也就是b列可以說是從左到右單調遞增的,但我們看c列和d列並沒有這個特性,它們只能在b列值相等的情況下這個小範圍內遞增,如第一葉子節點的第1、2個元素和第二個葉子節點的後三個元素。

由於聯合索引是上述那樣的

索引構建方式及儲存結構,所以聯合索引只能從多列索引的第一列開始查詢。所以如果你的查詢條件不包含b列如(c,d)、(c)、(d)是無法應用快取的,以及跨列也是無法完全用到索引如(b,d),只會用到b列索引。

這就像我們的**本一樣,有名和姓以及**,名和姓就是聯合索引。在姓可以以姓的首字母排序,姓的首字母相同的情況下,再以名的首字母排序。

我們知道名和姓是很快就能夠從姓的首字母索引定位到姓,然後定位到名,進而找到**號碼,因為所有的姓從上到下按照既定的規則(首字母排序)是有序的,而名是在姓的首字母一定的條件下也是按照名的首字母排序的,但是整體來看,所有的名放在一起是無序的,所以如果只知道名查詢起來就比較慢,因為無法用已排好的結構快速查詢。

如下列舉一些sql的索引使用情況

select

*from t1 where b =

12and c =

14and d =

3;--

全值索引匹配 三列都用到

select

*from t1 where b =

12and c =

14and e =

'xml

';--

應用到兩列索引

select

*from t1 where b =

12and e =

'xml

';--

應用到一列索引

select

*from t1 where b =

12and c >=

14and e =

'xml

';--

應用到bc兩列索引及索引條件下推優化

select

*from t1 where b =

12and d =

3;--

應用到一列索引 因為不能跨列使用索引 沒有c列 連不上

select

*from t1 where c =

14and d =

3;--

無法應用索引,違背最左匹配原則

聯合索引在B 樹上的結構

前言 最近在學習mysql的儲存引擎和索引的知識。看了許多篇介紹myisam和innodb的索引的例子,都能理解。像這張索引圖 ps 該圖來自大神張洋的 mysql索引背後的資料結構及演算法原理 一文。但許多文章講述的都是單列索引,我很好奇聯合索引對應的結構圖是怎樣的。疑惑 聯合索引的結構是怎樣的 ...

聯合索引在B 樹上的結構

一級索引 二級聯合索引 假設這是乙個多列索引 col1,col2,col3 對於葉子節點,是這樣的 ps 該圖改自 mysql索引背後的資料結構及演算法原理 一文的配圖。也就是說,聯合索引 col1,col2,col3 也是一棵b tree,其非葉子節點儲存的是第乙個關鍵字的索引,而葉節點儲存的則是...

聯合索引在B 樹上的結構介紹

最近在學習mysql的儲存引擎和索引的知識。看了許多篇介紹myisam和innodb的索引的例子,都能理解。像這張索引圖 ps 該圖來自大神張洋的 mysql索引背後的資料結構及演算法原理 一文。但許多文章講述的都是單列索引,我很好奇聯合索引對應的結構圖是怎樣的。比方說聯合索引 col1,col2,...