索引是什麼
索引是為了加速對錶中資料行的檢索而建立的一種分散儲存的資料結構 解釋:索引和資料都是存在磁碟的,需要把資料拿到記憶體中進行比較查詢到對應的資料,如果沒有用索引,就會從磁碟全盤掃描,如果走索引,他會通過索引找到對應的資料位置,從而直接去取資料

為什麼要用索引
- 索引能極大的減少儲存引擎需要掃描的資料量
- 索引可以把隨機IO變成順序IO
- 索引可以幫助我們在進行分組、排序等操作時,避免使用臨時表
為什麼是B+Tree
二叉樹

平衡二叉樹

- 層級太深 層級的深度決定了他的IO操作次數,IO操作耗時大
- 每一個節點資料太少 沒有很好的利用操作磁碟IO的資料交換特性,也沒有利用好磁碟IO的預讀能力(空間區域性性原理),從而帶來頻繁的IO操作
解釋:查詢從根節點開始,一次比較就需要把一個節點資料載入到記憶體中進行判斷(一次IO),所以層級越深,比較和IO次數就越多。 預讀:每一次IO時,不僅僅把當前磁碟地址的資料載入到記憶體,同時也把相鄰資料也載入到記憶體緩衝區中。當訪問一個地址資料的時候,與其相鄰的資料很快也會被訪問到。每次磁碟IO讀取的資料我們稱之為一頁(page)。一頁的大小與作業系統有關,一般為4k或者8k。這也就意味著讀取一頁內資料的時候,實際上發生了一次磁碟IO,mysql為16K
多路平衡查詢樹 B-Tree

多路:節點的子節點最多的個數
關鍵字個數=路數-1
好處:隨著路數的增多,可以儲存更多的資料,層級也會變得更短,這樣就減少了IO操作
Mysql的B+Tree

B+Tree與B-Tree的區別
- B+節點關鍵字搜尋採用閉合區間
- B+非葉子節點不儲存資料相關資訊,只儲存關鍵字和子節點的引用
- B+關鍵字對應的資料儲存在葉子節點中
- B+葉子節點是順序排列的,並且相鄰節點具有順序引用的關係
為什麼選用B+Tree
- B+樹是B-樹的變種,他包含B-樹的優勢
- B+樹掃庫、表能力更強(覆蓋索引如果要掃庫或者掃表的話(什麼是覆蓋索引,後面會說)B-樹要掃描樹所有節點,B+樹只要掃描葉子節點)
- B+樹的磁碟讀寫能力更強(因為非葉子節點不存資料,所以每頁儲存的關鍵字會更多,路數會更多)
- B+樹的排序能力更強
- B+樹的查詢效率更加穩定(B+樹永遠要找到葉子節點,因為資料是存在葉子節點,所以IO次數是一定的,B-樹找到節點就可以返回,同一個樹不同資料IO次數是不一樣的)
Mysql B+Tree索引體現形式
Mysql有很多儲存引擎,建立表的時候指定對應的儲存引擎,常用的是Myisam和Innodb,預設為Innodb
Myisam索引
Myisam建立表的時候會有三個檔案:.frm檔案(表定義檔案)、.MYD檔案(資料)、.MYI檔案(索引)


InnoDB索引
InnoDB建立表的時候只有兩個檔案:.frm檔案(表定義檔案)、.idb檔案(資料) 索引和資料放在一起

InnoDB都會以主鍵為索引來組織資料的儲存,如果沒有指定主鍵,它會定義一個隱藏的預設的主鍵索引
聚集索引:指索引項的排序方式和表中資料記錄排序方式一致的索引
聚簇索引:聚簇索引並不是一種單獨的索引型別,而是一種資料儲存方式。術語“聚族”表示資料行和相鄰的鍵值緊湊的儲存在一起。因為無法同時把資料行放在兩個不同的地方,所以一個表只能有一個聚族索引
所以InnoDB主鍵索引既是聚集索引也是聚簇索引
輔助索引:除了主鍵索引之外的索引

Innodb vs Myisam

索引的其他補充
- 列的離散性:離散性越高選擇性就越好
- 最左匹配原則:對索引中關鍵字進行對比,一定是從左往右依次進行,且不可跳過
- 聯合索引:節點中關鍵字是多個,單列索引是特殊的聯合索引。舉例a,b,c三列上建立一個聯合索引,create index abc on users(a,b,c) 一般會問哪些會走索引,走什麼索引,a、a,b、a,b,c、a,c(走a列,c列是不走索引的)會走索引,b,b,c,c是不走索引的,根據最左匹配原則,一定是從左開始的,abc列值會在節點中從左到右順序排列的
- 覆蓋索引:如果查詢列可通過索引節點中的關鍵字直接返回,則該索引稱為覆蓋索引,覆蓋索引可減少資料庫IO,可提高查詢效能,因為查索引就可以直接返回了,所以一般查詢最少列
- 索引列的資料長度能少則少
主鍵為什麼建議用int 自增長 而不用uuid原因:1.uuid長度比int長,所以用int,節點儲存的關鍵字會更多,路數會比uuid多,層級會更短。2.主鍵一般是不變的,順序自增長,uuid是不定的,當增加資料時,自增長樹的改動會遠遠比uuid的改動下
- 索引不是越多越好,越全越好,因為索引是需要維護的,多了也會影響效能