聯合索引在B+樹上的結構介紹
前言
最近在學習MySQL的儲存引擎和索引的知識。看了許多篇介紹MyISAM和InnoDB的索引的例子,都能理解。
像這張索引圖:
PS:該圖來自大神張洋的《MySQL索引背後的資料結構及演算法原理》一文。
但許多文章講述的都是單列索引,我很好奇聯合索引對應的結構圖是怎樣的。
疑惑:聯合索引的結構是怎樣的
比方說聯合索引 (col1, col2,col3),我知道在邏輯上是先按照col1進行排序再按照col2進行排序最後再按照col3進行排序。因此如果是select * from table where col1 = 1 and col3 = 3的話,只有col1的索引部分能生效。但是其物理結構上這個聯合索引是怎樣存在的,我想不懂。
解答:聯合索引的結構
上網查閱了許多資料,總算有點眉目了。
假設這是一個多列索引(col1, col2,col3),對於葉子節點,是這樣的:
PS:該圖改自《MySQL索引背後的資料結構及演算法原理》一文的配圖。
也就是說,聯合索引(col1, col2,col3)也是一棵B+Tree,其非葉子節點儲存的是第一個關鍵字的索引,而葉節點儲存的則是三個關鍵字col1、col2、col3三個關鍵字的資料,且按照col1、col2、col3的順序進行排序。
配圖可能不太讓人滿意,因為col1都是不同的,也就是說在col1就已經能確定結果了。自己又畫了一個圖(有點醜),col1表示的是年齡,col2表示的是姓氏,col3表示的是名字。如下圖:
PS:對應地址指的是資料記錄的地址。
如圖,聯合索引(年齡, 姓氏,名字),葉節點上data域儲存的是三個關鍵字的資料。且是按照年齡、姓氏、名字的順序排列的。
因此,如果執行的是:
select * from STUDENT where 姓氏='李' and 名字='安';
或者
select * from STUDENT where 名字='安';
那麼當執行查詢的時候,是無法使用這個聯合索引的。因為聯合索引中是先根據年齡進行排序的。如果年齡沒有先確定,直接對姓氏和名字進行查詢的話,就相當於亂序查詢一樣,因此索引無法生效。因此查詢是全表查詢。
如果執行的是:
select * from STUDENT where 年齡=1 and 姓氏='李';
那麼當執行查詢的時候,索引是能生效的,從圖中很直觀的看出,age=1的是第一個葉子節點的前6條記錄,在age=1的前提下,姓氏=’李’的是前3條。因此最終查詢出來的是這三條,從而能獲取到對應記錄的地址。
如果執行的是:
select * from STUDENT where 年齡=1 and 姓氏='黃' and 名字='安';
那麼索引也是生效的。
而如果執行的是:
select * from STUDENT where 年齡=1 and 名字='安';
那麼,索引年齡部分能生效,名字部分不能生效。也就是說索引部分生效。
因此我對聯合索引結構的理解就是B+Tree是按照第一個關鍵字進行索引,然後在葉子節點上按照第一個關鍵字、第二個關鍵字、第三個關鍵字…進行排序。
最左原則
而之所以會有最左原則,是因為聯合索引的B+Tree是按照第一個關鍵字進行索引排列的。
有助於理解聯合索引的一個例子
from csdn論壇:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
最後
這樣的解釋,參考過別人的文章,自己也有思考過,但並不能確定實際上的結構就是這種。但是,也算是學到了許多東西,像是明白了為什麼會有最左原則的存在。