MySQL InnoDB和MyISAM索引結構簡析與對比


B+樹

我們這裏關注B+樹的兩個特性:

  1. 葉子節點包含數據data(data並不特指數據庫中的某一行數據,也可以是某個數值,指針等)

  2. 葉子節點均在同一層,且每個節點均可以直接找到上一個或者下一個節點(雙向指針,比常規的B+樹多了一個指向上一個的指針)


    webp

    4階 B+樹

InnoDB 聚簇索引

聚簇索引:行數據與鍵值(主鍵)緊湊地存儲在一起;

InnoDB中表現爲:B+樹葉子節點的data用於存放行數據(包含主鍵值、其他列數據、回滾指針、事務id等),物理上索引數據與行數據都放在同一個文件中(.ibd

以用戶表爲例,id爲主鍵,另外name存在索引idx_name

CREATE TABLE `t_user` (  `id` bigint,  `name` varchar(10),  `age` int,
  PRIMARY KEY (`id`),  KEY `idx_name` (`name`)
);

插入數據:

insert into t_user (id,`name`,age) values(1,'n7',10),
(2,'n6',20),
(3,'n5',30),
(4,'n4',40),
(5,'n3',50),
(6,'n2',60),
(7,'n1',70)

聚簇索引對應的結構爲:

webp

InnoDB聚簇索引,注:數據庫中B+樹的階數要比這個大得多

如果沒有定義主鍵,InnoDB會選擇一個唯一的非空索引代替。如果沒有這樣的索引,InnoDB會隱式定義一個主鍵(DB_ROW_ID)來作爲聚簇索引。

最好避免使用隨機的主鍵(比如UUID)
InnoDB中磁盤管理的最小單位爲頁(InnoDB page,默認16KB),一頁能存放的數據記錄數量是有限的,根據B+樹的特性,需要保證頁內數據是按主鍵排序存儲的。
當主鍵隨機插入時,如果新的記錄可能需要插入之前記錄的中間,導致需要強制移動之前的記錄;如果需要插入一個已經滿了的頁中時,會導致頁分裂(新建兩個頁並把原數據複製過去,成本很高)。

InnoDB 二級索引

二級索引,或者叫非聚簇索引;與聚簇索引最大的不同是:B+樹的data存放的並不是行數據,而是主鍵值
以上面用戶表爲例,當select * from t_user where name='n1'時,會先通過idx_name索引找到n2對應的主鍵的值(id=7),再通過主鍵值找到行數據 [7,n1,70] ,故稱二級索引。

webp

InnoDB二級索引


覆蓋索引:當select的列的已經在二級索引的樹中時,並不需要再通過主鍵值找到整行的數據即可返回。比如select id,name from t_user where name='n2' ,name和id均可在idx_name索引的葉子節點上,故不用主鍵回查聚簇索引了。像這種二級索引覆蓋到所有查詢列數據的情況叫覆蓋索引。使用explain這個查詢時可以看到Extra中包含Using index

MyISAM 索引

與InnoDB不同,MyISAM並不使用聚簇索引,MyISAM的索引數據和行數據是分開的,物理上分別爲.myi索引數據文件和.myd行數據文件(InnoDB 索引和行數據均在.idb文件中)

MyISAM中,主鍵索引和其他的一般索引在數據結構上並沒有什麼區別,B+樹的data存放的均是數據行地址

id主鍵索引:

webp

MyISAM主鍵索引


name一般索引

webp

MyISAM一般索引


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章