mysql联合索引的数据结构
一、本文主要講解的內容有:
在分享這篇文章之前,我在網上查了關于MySQL聯合索引在B+樹上的存儲結構這個問題,翻閱了很多博客和技術文章,其中有幾篇講述的與事實相悖。慶幸的是看到搜索引擎列出的有一條是來自思否社區的問答,有答主回答了這個問題,貼出一篇文章和一張圖以及一句簡單的描述。PS:貼出的文章鏈接已經打不開了。
所以在這樣的條件下這篇文章就誕生了。
二、聯合索引的存儲結構
下面就引用思否社區的這個問答來展開我們今天要討論的聯合索引的存儲結構的問題。
來自思否的提問,聯合索引的存儲結構,有碼友回答如下:
聯合索引 bcd , 在索引樹中的樣子如圖 , 在比較的過程中 ,先判斷 b 再判斷 c 然后是 d 。
- 例子:
首先,表T1有字段a,b,c,d,e,其中a是主鍵,除e為varchar其余為int類型,并創建了一個聯合索引idx_t1_bcd(b,c,d),然后b、c、d三列作為聯合索引,在B+樹上的結構正如上圖所示。聯合索引的所有索引列都出現在索引數上,并依次比較三列的大小。上圖樹高只有兩層不容易理解,下面是假設的表數據以及我對其聯合索引在B+樹上的結構圖的改進。PS:基于InnoDB存儲引擎
T1表的表數據如下:
bcd聯合索引在B+樹上的結構圖:
我們先看T1表,他的主鍵暫且我們將它設為整型自增的 (PS:至于為什么是整型自增章《MySQL索引那些事》有詳細介紹這里不再多說) ,InnoDB會使用主鍵索引在B+樹維護索引和數據文件,然后我們創建了一個聯合索引(b,c,d)也會生成一個索引樹,同樣是B+樹的結構,只不過它的data部分存儲的是聯合索引所在行的主鍵值(上圖葉子節點紫色背景部分),至于為什么輔助索引data部分存儲主鍵值《MySQL索引那些事》也有介紹,感興趣或還不知道的可以去看一下。
- 下面我們結合這兩個圖來解釋一下:
對于聯合索引來說只不過比單值索引多了幾列,而這些索引列全都出現在索引樹上。對于聯合索引,存儲引擎會首先根據第一個索引列排序,如上圖我們可以單看第一個索引列,橫著看,如,1 1 5 12 13....他是單調遞增的;如果第一列相等則再根據第二列排序,依次類推就構成了上圖的索引樹,上圖中的b列都等于1時,則根據c排序,此時c列也相等則按d列排序,如:1 1 4 ,1 1 5,c=4在c=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值,再從主鍵索引樹上找到最終數據。
四、最左前綴匹配原則
之所以會有最左前綴匹配原則和聯合索引的索引構建方式及存儲結構是有關系的。首先我們創建的index_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列索引。
五、后記
MySQL索引及知識非常廣泛,本文只是涉及到其中一部分。如與排序(ORDER BY)相關的索引優化及覆蓋索引(Covering index)的話題本文并未涉及,同時除B-Tree索引外MySQL還根據不同引擎支持的哈希索引、全文索引等等本文也并未涉及。如果有機會,希望再對本文未涉及的部分進行補充吧。
本文轉自:https://juejin.im/post/6844904073955639304
總結
以上是生活随笔為你收集整理的mysql联合索引的数据结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原型到底应该画到什么程度?被骂N次后我得
- 下一篇: CentOS安装Mysql8各种坑。。。