一、mysql的Innodb引擎中,主鍵索引和普通索引的工作原理
在InnoDB中,表都是根據主鍵順序以索引的形式存放的,這種存儲方式的表稱為索引組織表。InnoDB使用了B+樹索引模型,所以數據都是存儲在B+樹中的。
每一個索引在InnoDB里面對應一棵B+樹。
假設,我們有一個主鍵列為ID的表,表中有字段k,并且在k上有索引。
這個表的建表語句是:
mysql> create table T(
id int primary key,
k int not null,
name varchar(16),
index (k))engine=InnoDB;
主鍵索引的葉子節點存的是整行數據。在InnoDB里,主鍵索引也被稱為聚簇索引(clustered index)。
非主鍵索引的葉子節點內容是主鍵的值。在InnoDB里,非主鍵索引也被稱為二級索引(secondary index)或普通索引。
根據上面的索引結構說明,我們來討論一個問題:基于主鍵索引和普通索引的查詢有什么區別?
如果語句是select * from T where ID=500,即主鍵查詢方式,則只需要搜索ID這棵B+樹;如果語句是select * from T where k=5,即普通索引查詢方式,則需要先搜索k索引樹,得到ID的值為500,再到ID索引樹搜索一次。這個過程稱為回表。 也就是說,基于非主鍵索引的查詢需要多掃描一棵索引樹。這也是為什么說我們要盡量使用主鍵查詢了。延伸閱讀:
二、索引維護
B+樹為了維護索引有序性,在插入新值的時候需要做必要的維護。以上面這個圖為例,如果插入新的行ID值為700,則只需要在R5的記錄后面插入一個新記錄。如果新插入的ID值為400,就相對麻煩了,需要邏輯上挪動后面的數據,空出位置。
而更糟的情況是,如果R5所在的數據頁已經滿了,根據B+樹的算法,這時候需要申請一個新的數據頁,然后挪動部分數據過去。這個過程稱為頁分裂。在這種情況下,性能自然會受影響。
除了性能外,頁分裂操作還影響數據頁的利用率。原本放在一個頁的數據,現在分到兩個頁中,整體空間利用率降低大約50%。
當然有分裂就有合并。當相鄰兩個頁由于刪除了數據,利用率很低之后,會將數據頁做合并。合并的過程,可以認為是分裂過程的逆過程。