數(shù)據(jù)庫索引意在提升檢索效率。
通過創(chuàng)建唯一索引可以保證數(shù)據(jù)庫表中每一行數(shù)據(jù)的唯一性。排序后可以將隨機(jī)的I/O轉(zhuǎn)換成順序I/O。
索引是如何提高檢索速度的?
將無序的數(shù)據(jù)存儲(chǔ)轉(zhuǎn)為相對有序的數(shù)據(jù)。
索引為什么不是越多越好?
- 對表中的數(shù)據(jù)進(jìn)行insert/update/delete時(shí),索引需要?jiǎng)討B(tài)維護(hù),占用時(shí)間。
- 索引建立后需要占用存儲(chǔ)空間,如果是聚簇索引,占用的存儲(chǔ)空間更大。
MySQL數(shù)據(jù)庫主要使用的兩種數(shù)據(jù)結(jié)構(gòu)
-
哈希索引
image.png
(圖片來源于網(wǎng)絡(luò),侵刪)
哈希索引檢索速度很快,但是也存在一定的局限性:
1)哈希索引沒有辦法利用索引完成排序
2)有重復(fù)鍵值的情況下,會(huì)發(fā)生哈希碰撞,索引效率較低
3)不支持范圍查詢
4)不支持最左匹配原則 -
B+Tree索引
image.png
(圖片來源于網(wǎng)絡(luò),侵刪)
每一頁存在一個(gè)record_type:
0:普通的用戶記錄
1:目錄項(xiàng)記錄
2:最小記錄
3:最大記錄
目錄項(xiàng)記錄只有主鍵值和頁的編號(hào)兩個(gè)列,而普通的用戶記錄的列是用戶自己定義的(Innodb為列,MyISAM的葉子節(jié)點(diǎn)存儲(chǔ)記錄的指針),可能包含很多列,另外還有InnoDB自己添加的隱藏列。
Innodb和MySIAM實(shí)現(xiàn)B+Tree的方式:聚簇索引 & 非聚簇索引

(圖片來源于網(wǎng)絡(luò),侵刪)
聚簇索引:
葉子節(jié)點(diǎn)存儲(chǔ)了完整的用戶記錄
在Innodb中,會(huì)自動(dòng)創(chuàng)建聚簇索引,聚簇索引就是數(shù)據(jù)的存儲(chǔ)方式。一張表有且僅有一個(gè)聚簇索引。
1)如果表定義了PK,則PK就是聚簇索引
2)如果表沒有定義PK,則第一個(gè)not NULL unique列就是聚簇索引
3)否則,Innodb會(huì)創(chuàng)建一個(gè)隱藏的row-id作為聚簇索引
普通索引(二級(jí)索引,輔助索引,非聚簇索引)
對于Innodb來說二級(jí)索引的葉子節(jié)點(diǎn)存放的是索引列的值與主鍵
MyISAM因?yàn)榇娣诺娜侵麈I和行號(hào),意味著MyISAM中建立的索引全部都是二級(jí)索引,那么MyISAM均需要回表查詢。
索引覆蓋
explain查詢計(jì)劃優(yōu)化,即explain的輸出結(jié)果Extra字段為Using index時(shí),能夠觸發(fā)索引覆蓋。
只需要在一棵索引樹上就能獲取SQL所需的所有列數(shù)據(jù),無需回表,速度更快。
常見的方法是:將被查詢的字段,建立到聯(lián)合索引里去。
哪些情況可以利用索引覆蓋來優(yōu)化SQL:
1)全表count查詢優(yōu)化
2)列查詢回表優(yōu)化
3)分頁查詢
復(fù)合索引的范圍查詢與最左原則:
- SQL語句中where子句中范圍查詢之后的列無法使用聯(lián)合索引
- 在mysql建立聯(lián)合索引時(shí)會(huì)遵循最左前綴匹配的原則,即最左優(yōu)先,在檢索數(shù)據(jù)時(shí)從聯(lián)合索引的最左邊開始匹配

