1. 程式人生 > >MySQL中MyISAM和InnoDB對B-Tree索引不同的實現方式

MySQL中MyISAM和InnoDB對B-Tree索引不同的實現方式

索引是 MySQL資料庫很重要的一部分,它對資料表查詢效能的好壞起著決定性的作用,對大表尤甚。
作為索引中最為常見的一種型別,B-Tree索引大都採用的是 B+Tree資料結構來儲存資料(NDB叢集儲存引擎內部實際上採用 T-Tree結構儲存這種索引)。B-Tree通常也意味著所有的值都是按順序儲存的。
大多數的 MySQL引擎都支援這種索引,而不同的儲存引擎以不同的方式來實現 B-Tree索引,效能方面各有優劣。
下面分別講述 MyISAM 和 InnoDB 的B-Tree索引實現方式。

MyISAM索引的實現

MyISAM索引檔案和資料檔案是分離的,索引檔案僅儲存記錄所在頁的指標(物理位置),通過這些地址來讀取頁,進而讀取被索引的行。下圖是MyISAM的索引原理圖:(為了簡化,一個頁內只存放了兩條記錄。)

這裡寫圖片描述

上圖所提供的示例表字段有Col1(ID)、Col2(age)、Col3(name)三個,其中Col1為Primary Key(主鍵),上圖很好地說明了樹中葉子儲存的是對應行的物理位置。通過該值,儲存引擎能順利地進行回表查詢,得到一行完整記錄。同時,每個葉子頁也儲存了指向下一個葉子頁的指標。從而方便葉子節點的範圍遍歷。
而對於二級索引,在 MyISAM儲存引擎中以與上圖同樣的方式實現,這也說明了 MyISAM的索引方式是“非聚集的”,與 Innodb的“聚集索引”形成了對比。

InnoDB索引的實現

聚集索引

與 MyISAM相同的一點是,InnoDB 也採用 B+Tree這種資料結構來實現 B-Tree索引。而很大的區別在於,InnoDB 儲存引擎採用“聚集索引”的資料儲存方式實現B-Tree索引,所謂“聚集”,就是指資料行和相鄰的鍵值緊湊地儲存在一起,注意 InnoDB 只能聚集一個葉子頁(16K)的記錄(即聚集索引滿足一定的範圍的記錄),因此包含相鄰鍵值的記錄可能會相距甚遠。

在 InnoDB 中,表被稱為 索引組織表(index organized table),InnoDB 按照主鍵構造一顆 B+Tree (如果沒有主鍵,則會選擇一個唯一的並且非空索引替代,如果沒有這樣的索引,InnoDB則會隱式地定義一個主鍵來作為聚集索引),同時葉子頁中存放整張表的行記錄資料,也可以將聚集索引的葉子節點稱為資料頁,非葉子頁可以看做是葉子頁的稀疏索引。

下圖說明了 InnoDB聚集索引的實現方式,同時也體現了一張 innoDB表的結構,可以看到,InnoDB 中,主鍵索引和資料是一體的,沒有分開。:

這裡寫圖片描述

這種實現方式,給予了 InnoDB 按主鍵檢索的超高效能。可以有目的性地選擇聚集索引,比如一個郵件表,可以選擇使用者ID來聚集資料,這樣只需要從磁碟讀取較少並且連續的資料頁就能獲得某個id的使用者全部的郵件,避免了讀取分散頁時所耗費的隨機I/O。

輔助索引

而對於輔助索引,InnoDB採用的方式是在葉子頁中儲存主鍵值,通過這個主鍵值來回表(上圖)查詢到一條完整記錄,因此按輔助索引檢索實際上進行了二次查詢,效率肯定是沒有按照主鍵檢索高的。下圖是輔助索引的實現方式:

這裡寫圖片描述

由於每個輔助索引都包含主鍵索引,因此,為了減小輔助索引所佔空間,我們通常希望 InnoDB 表中的主鍵索引儘量定義得小一些(值得一提的是,MySIAM會使用字首壓縮技術使得索引變小,而InnoDB按照原資料格式進行儲存。),並且希望InnoDB的主鍵是自增長的,因為如果主鍵並非自增長,插入時,由於寫入時亂序的,會使得插入效率變低。

最後,我們要知道,B-Tree索引適用於等值匹配、範圍匹配、鍵字首匹配,這裡的字首指的是最左字首。
.