下面就引用思否社群的這個問答來展開我們今天要討論的聯合索引的儲存結構的問題。
來自思否的提問,聯合索引的儲存結構(有碼友回答如下:
聯合索引 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+樹上的結構圖
t1表通過這倆圖我們心裡對聯合索引在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列索引。
這就像我們的**本一樣,有名和姓以及**,名和姓就是聯合索引。在姓可以以姓的首字母排序,姓的首字母相同的情況下,再以名的首字母排序。
如:m
毛 不易 178********
馬 化騰 183********
馬 雲 188********
z
張 傑 189********
張 靚穎 138********
張 藝興 176********
我們知道名和姓是很快就能夠從姓的首字母索引定位到姓,然後定位到名,進而找到**號碼,因為所有的姓從上到下按照既定的規則(首字母排序)是有序的,而名是在姓的首字母一定的條件下也是按照名的首字母排序的,但是整體來看,所有的名放在一起是無序的,所以如果只知道名查詢起來就比較慢,因為無法用已排好的結構快速查詢。
到這裡大家是否明白了為啥會有最左字首匹配原則了吧。
如下列舉一些sql的索引使用情況
1到這裡mysql索引的聯合索引的儲存結構及查詢方式就講完了,本人能力有限,也是站著前人的肩膀上創作的此文,因為看到搜尋引擎的搜尋結果前幾個技術文章中有存在講述不清或講述有誤的地方,所以自己才總結出這篇文章分享給大家,如有不對的地方一定要指正哦,謝謝了。select
*from t1 where b =
12and c =
14and d =
3;--
全值索引匹配 三列都用到23
select
*from t1 where b =
12and c =
14and e =
'xml
';--
應用到兩列索引45
select
*from t1 where b =
12and e =
'xml
';--
應用到一列索引67
select
*from t1 where b =
12and c >=
14and e =
'xml
';--
應用到bc兩列索引及索引條件下推優化89
select
*from t1 where b =
12and d =
3;--
應用到一列索引 因為不能跨列使用索引 沒有c列 連不上
1011
select
*from t1 where c =
14and d =
3;--
無法應用索引,違背最左匹配原則
這篇文章斷斷續續利用工作之餘畫圖加寫作用了兩三天,主要內容就是上面這些了。不可否認,這篇文章在一定程度上有紙上談兵之嫌,因為我本人對mysql的使用屬於菜鳥級別,更沒有太多資料庫調優的經驗,在這裡高談闊論實屬慚愧。就當是我個人的一篇學習筆記了。
另外,mysql索引及知識非常廣泛,本文只是涉及到其中一部分。如與排序(order by)相關的索引優化及覆蓋索引(covering index)的話題本文並未涉及,同時除b-tree索引外mysql還根據不同引擎支援的雜湊索引、全文索引等等本文也並未涉及。如果有機會,希望再對本文未涉及的部分進行補充吧。
創作不易,如果對你有幫助,請不要吝嗇你的贊,這對我是很大的鼓勵~
覺得好看,請點這裡↓
↓
↓
聯合索引在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,...