3、赫敏 格蘭杰 --- 淺談索引

低年級時期的赫敏 真的好漂亮

InnoDB中的索引模型

在InnoDB中表都是跟隨主鍵順序,以索引的形式存放的。這種存儲方式的表稱為索引組織表。
InnoDB采用了B+tree索引模型,所以數(shù)據(jù)都是存儲在B+??中的

每一個索引在InnoDB中對應(yīng)一顆 B+ ??

主鍵索引的子葉節(jié)點(diǎn)存的是整行數(shù)據(jù)。在InnoDB里,主鍵索引也叫聚簇索引

非主鍵索引的子葉節(jié)點(diǎn)內(nèi)容是主鍵的值。在InnoDB里,非主鍵索引也叫二級索引。

基于主鍵索引和普通索引查詢的區(qū)別?

mysql> create table T(
id int primary key, 
k int not null, 
name varchar(16),
index (k))engine=InnoDB;

select * from T where id=500; 對于主鍵查詢方式,只需要搜索ID這顆B+??
select * from T where k=5; 普通索引查詢方式,首先搜索k索引??,獲得對應(yīng)的ID值,在用Id在 id索引??在搜索一次,這個過程叫做回表。
so,赫敏溫馨提醒 :盡量使用主鍵索引咯~~~

索引的維護(hù)

image.png

B+??為了維護(hù)索引的有序性,在插入新值的時候就需要做必要的維護(hù),以上面這個圖為例,如果插入新的行 ID 值為 700,,則只需要在 R5 的記錄后面插入一個新記錄。如果新插入的 ID 值為 400,就相對麻煩了需要邏輯上挪動后面的數(shù)據(jù),空出位置。

而更糟的情況是,如果 R5 所在的數(shù)據(jù)頁已經(jīng)滿了,根據(jù) B+ 樹的算法,這時候需要申請一個新的數(shù)據(jù)頁,然后挪動部分?jǐn)?shù)據(jù)過去。這個過程稱為頁分裂。在這種情況下,性能自然會受影響。
除了性能外,頁分裂操作還影響數(shù)據(jù)頁的利用率。原本放在一個頁的數(shù)據(jù),現(xiàn)在分到兩個頁中,整體空間利用率降低大約 50%。
當(dāng)然有分裂就有合并。當(dāng)相鄰兩個頁由于刪除了數(shù)據(jù),利用率很低之后,會將數(shù)據(jù)頁做合并。合并的過程,可以認(rèn)為是分裂過程的逆過程。



mysql> create table T (
ID int primary key,
k int NOT NULL DEFAULT 0, 
s varchar(16) NOT NULL DEFAULT '',
index k(k))
engine=InnoDB;

insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');

如果我執(zhí)行 select * from T where k between 3 and 5,需要執(zhí)行幾次樹的搜索操作,會掃描多少行?

1、在 k 索引樹上找到 k=3 的記錄,取得 ID = 300...
2、再到 ID 索引樹查到 ID=300 對應(yīng)的 R3;
3、在 k 索引樹取下一個值 k=5,取得 ID=500;
4、再回到 ID 索引樹查到 ID=500 對應(yīng)的 R4;
5、在 k 索引樹取下一個值 k=6,不滿足條件,循環(huán)結(jié)束。

在這個過程中,回到主鍵索引樹搜索的過程,我們稱為回表。可以看到,這個查詢過程讀了 k索引樹的 3 條記錄(步驟 1、3 和 5),回表了兩次(步驟 2 和 4)。

索引覆蓋

如果執(zhí)行的語句是 select ID from T where k between 3 and 5,這時只需要查 ID 的值,而ID 的值已經(jīng)在 k 索引樹上了,因此可以直接提供查詢結(jié)果,不需要回表。也就是說,在這個查詢里面,索引 k 已經(jīng)“覆蓋了”我們的查詢需求,我們稱為索引覆蓋。

由于索引覆蓋可以減少索引樹的搜索次數(shù),顯著提升查詢性能,所以使用覆蓋索引是一個常用的性能提升手段

最左前綴原則

B+ 樹這種索引結(jié)構(gòu),可以利用索引的“最左前綴”,來定位記錄。
在建立聯(lián)合索引的時候,如何安排索引內(nèi)的字段順序。
第一原則是,如果通過調(diào)整順序,可以少維護(hù)一個索引,那么這個順序往往就是需要優(yōu)先考慮采用的。
還要考慮到空間原則


聯(lián)合索引(name, age)


image.png

可以看到。索引項(xiàng)是按照索引定義里面出現(xiàn)的字段順序排序的。

索引下推

mysql> select * from tuser where name like '張 %' and age=10 and ismale=1;

Mysql5.6 引入索引下推優(yōu)化(index condition pushdown) ,在索引遍歷過程中,
對索引包含的字段先進(jìn)行判斷,直接過濾掉不符合條件的記錄,減少回表次數(shù)。


image.png

鳴謝 林曉斌 發(fā)布在極客時間上的Mysql45講 格蘭杰用金加隆訂閱的哦~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容