InnoDB索引存儲結構


原創轉載請注明出處:https://www.cnblogs.com/agilestyle/p/11429438.html

 

InnoDB默認創建的主鍵索引是聚簇索引(Clustered Index),其它索引都屬於輔助索引(Secondary Index),也被稱為二級索引或非聚簇索引。

接下來通過一個簡單的例子,說明下這兩種索引在存儲數據中的具體實現。

首先創建一張商品表,如下:

1 CREATE TABLE `merchandise`  (
2   `id` int(11) NOT NULL,
3   `serial_no` varchar(20)  DEFAULT NULL,
4   `name` varchar(255) DEFAULT NULL,
5   `unit_price` decimal(10, 2) DEFAULT NULL,
6   PRIMARY KEY (`id`) USING BTREE
7 ) CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

然后新增了以下幾行數據,如下:

使用的是InnoDB存儲引擎,由於InnoDB使用的是聚簇索引,聚簇索引中的葉子節點則記錄了主鍵值、事務id、用於事務和MVCC的回流指針以及所有的剩余列,如下圖所示:

基於上面的圖示,如果需要根據商品編碼serial_no查詢商品,就需要將商品編碼serial_no列作為一個索引列。此時創建的索引是一個輔助索引,但葉子節點存儲的就不是行指針了,而是主鍵值,並以此來作為指向行的指針。這樣的好處就是當行發生移動或者數據分裂時,不用再維護索引的變更。

 

回表

如果使用主鍵索引查詢商品,則會按照B+樹的索引找到對應的葉子節點,直接獲取到行數據:

1 select * from merchandise where id = 7

如果使用serial_no查詢商品,即使用輔助索引進行查詢,則會先檢索輔助索引中的B+樹的serial_no,找到對應的葉子節點,獲取主鍵值,然后再通過聚簇索引中的B+樹檢索到對應的葉子節點,然后獲取整行數據。這個過程叫做回表。

回表就是先通過輔助索引掃描出數據所在的行,再通過行主鍵id取出索引中未提供的數據,即基於非主鍵索引的查詢需要多掃描一棵索引樹。

 

覆蓋索引

假設只需要查詢商品的名稱、價格信息,有什么方式來避免回表呢?可以建立一個組合索引,即商品編碼、名稱、價格作為一個組合索引。如果索引中存在這些數據,查詢將不會再次檢索主鍵索引,從而避免回表。

從輔助索引中查詢得到記錄,而不需要通過聚簇索引查詢獲得,MySQL中將其稱為覆蓋索引。使用覆蓋索引的好處很明顯,不需要查詢出包含整行記錄的所有信息,因此可以減少大量的I/O操作。

通常在InnoDB中,除了查詢部分字段可以使用覆蓋索引來優化查詢性能之外,統計數量也會用到。例如, SELECT COUNT(*)時,如果不存在輔助索引,此時會通過查詢聚簇索引來統計行數,如果此時正好存在一個輔助索引,則會通過查詢輔助索引來統計行數,減少I/O操作。

 1 CREATE TABLE `test` (
 2   `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 3   `a` varchar(32) NOT NULL,
 4   `b` varchar(32) NOT NULL,
 5   `c` varchar(64) NOT NULL,
 6   `d` varchar(128) NOT NULL,
 7   `e` varchar(256) NOT NULL,
 8   `create_time` timestamp(3) NOT NULL DEFAULT current_timestamp(3),
 9   `update_time` timestamp(3) NOT NULL DEFAULT current_timestamp(3) ON UPDATE current_timestamp(3),
10   PRIMARY KEY (`id`),
11   KEY `idx_a_b` (`a`,`b`)
12 ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4;

 

Reference

https://time.geekbang.org/column/article/116369

https://zhuanlan.zhihu.com/p/27700617


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM