MySQL索引(一)索引基礎
索引是資料庫系統裡面最重要的概念之一。一句話簡單來說,索引的出現其實是為了提高資料查詢的效率,就像書的目錄一樣。
常見模型
索引的出現是為了提高查詢效率,但是實現索引的方式卻有很多種,這裡就介紹三種常見、也比較簡單的資料結構,它們分別是雜湊表、有序陣列和搜尋樹。
雜湊表
雜湊表是一種以key-value儲存資料的結構。通過雜湊函式把key換算成一個確定位置,然後把value放在這個資料的這個位置上。
但是當儲存的資料越來越多,就有可能出現兩個不同的key通過雜湊函式得到了一樣的值,這時候就出現衝突。而這時就引入連結串列來解決這種衝突了。
雜湊表這種資料結構適用於只有等值查詢的場景,時間複雜度為O(1),但是對於範圍查詢就必須全部遍歷了,時間複雜度為O(n)。
有序陣列
有序陣列在等值查詢和範圍查詢場景中的效能非常優秀。
但是需要往中間插入時就必須要挪動資料,時間複雜度很高。
搜尋樹
二叉搜尋樹在查詢和插入、刪除資料方面能夠中和上面兩種結構。查詢時間複雜為O(logn)、插入刪除的時間複雜度為O(logn)。
雖然二叉搜尋樹的搜尋效率很高,但是在大多數的資料庫並不使用二叉樹。原因是索引要寫在磁碟上。
磁碟上的隨機讀是很耗時間的,為了讓一個查詢儘量少地讀磁碟,就必須在查詢過程中訪問儘量少的資料塊。
那麼就不應該使用二叉樹,而是要使用“N”叉樹,這裡的“N”取決於資料塊的大小。
B+樹是為磁碟設計的一種平衡查詢樹。在B+樹中,所有記錄節點都是按鍵值的大小順序存放在同一層的葉子節點上,由各葉子節點指標進行連線。
索引型別
B+樹索引
資料庫中的B+樹索引可以分為主鍵索引和普通索引兩種,也有叫聚集索引(clustered index)和輔助索引(secondary index)
但不管是主鍵索引還是普通索引,都是使用B+樹的,即高度平衡的,葉子節點存放著所有資料。
主鍵索引
InnoDB儲存引擎表是索引組織表,即表中資料按主鍵順序存放。
主鍵索引就是按照每張表的主鍵構造一棵B+樹,同時葉子節點中存放的是行資料。每張表只能擁有一個主鍵索引。
普通索引
普通索引與主鍵索引的區別在於,普通索引的葉子節點並不包含行資料,而是包含主鍵。
基於主鍵索引和普通索引的查詢有什麼區別?
- 如果語句是select * from T where ID=500,即主鍵索引查詢方式,則只需要搜尋ID這棵B+樹;
- 如果語句是select * from T where k=5,即普通索引查詢,則需要先搜尋k索引樹,得到ID的值為500,再到ID索引樹搜尋一次。這個過程稱為回表。
也就是說,基於非主鍵索引的查詢需要多掃描一棵索引樹。因此我們應該儘量使用主鍵索引查詢。
雜湊索引
雜湊索引基於雜湊表實現,在MySQL中只有Memory引擎顯示支援雜湊索引,也是Memory引擎表的預設索引型別。
下面是建立Memory引擎表的語句:
CREATE TABLE `testhash` (
`fname` varchar(50) DEFAULT NULL,
`lname` varchar(50) DEFAULT NULL,
KEY `fname` (`fname`) USING HASH
) ENGINE=MEMORY;
雜湊索引限制
- 雜湊索引只儲存雜湊碼和指標,而不儲存欄位值,所以不能使用索引中的值來避免讀取行。不過訪問記憶體中的行速度非常快,所以對效能影響並不大。
- 雜湊索引資料並不是按照索引值順序儲存的,所以無法無法用於排序
- 雜湊索引不支援部分索引列查詢,因為雜湊索引始終是使用索引列的全部內容來計算雜湊碼。
- 雜湊索引只支援等值比較查詢,不支援範圍查詢。
- 雜湊衝突會影響查詢速度,此時需要遍歷索引中的行指標,逐行進行比較。
- 如果雜湊衝突很多,一些索引維護操作的代價會很高。
自定義雜湊索引
在InnoDB中,某些索引值被使用的非常頻繁的時候,它會在記憶體中基於B+樹的基礎上再建立一個雜湊索引,使其不必要從根節點就查詢。完全自動的內部行為,使用者無法配置或更改。