索引的目的就是為了提高查詢效率
索引常見模型
哈希表
一種以鍵-值存儲數據的結構
優點:
- 插入速度快
缺點: - 哈希索引做區間查詢的速度很慢
結論: - 這種結構適用于只有等值查詢的場景,比如memcached及其他一些NoSql引擎
有序數組
有序的數組結構
優點:
- 等值查詢(二分查找)和范圍查詢場景中性能優秀
缺點: - 插入速度慢、成本高
結論: - 這種結構適用于靜態存儲引擎
搜索樹
一種節點的左兒子小于父節點,父節點又小于右兒子的結構
優點:
- 查詢、更新效率高,為O(log(N))
缺點: - 索引不止在內存中,還要寫在磁盤上。二叉搜索樹的索引層次高,會產生高成本的磁盤IO。
結論 - 為了讓一個查詢盡量少地讀磁盤,必須讓查詢過程訪問經量少的數據庫(盡量少的進行磁盤IO)。一般用N叉樹,InnoDB的N在1200左右。
N叉搜索樹由于在讀寫上的性能優點,以及適配磁盤的訪問模式,已經被廣泛應用在數據庫引擎中了。
其他模型
- 跳表
- LSM樹
InnoDB的索引模型
在 InnoDB 中,表都是根據主鍵順序以索引的形式存放的,這種存儲方式的表稱為索引組織表。又因為前面我們提到的,InnoDB 使用了 B+ 樹索引模型,所以數據都是存儲在 B+ 樹中的。
InnoDB索引組織結構
圖中左邊為主鍵索引,右邊為非主鍵索引
- 主鍵索引的葉子節點存的是整行數據。在InnoDB里也被成為聚簇索引
- 非主鍵索引的葉子結點存的是主鍵的值。在InnoDB里也被稱為二級索引
這里引入一個問題:基于主鍵索引和普通索引的查詢有什么區別?
1 如果語句是 select * from T where ID=500,即主鍵查詢方式,則只需要搜索 ID 這棵 B+ 樹;
2 如果語句是 select * from T where k=5,即普通索引查詢方式,則需要先搜索 k 索引樹,得到 ID 的值為 500,再到 ID 索引樹搜索一次。這個過程稱為回表。
結論:基于非主鍵索引的查詢需要多掃描一棵索引樹。因此,我們在應用中應該盡量使用主鍵查詢。
索引維護
- B+樹為了維護索引有序性,在插入新值時需要做必要的維護。增加數據可能會出現頁分裂。刪除數據可能出現分裂過程的逆過程。
這里引入另一個問題:哪些場景下應該使用自增主鍵,而哪些場景下不應該
1 自增主鍵的插入數據模式,正符合了我們前面提到的遞增插入的場景。每次插入一條新記錄,都是追加操作,都不涉及到挪動其他記錄,也不會觸發葉子節點的分裂。
2 沒有其他索引時,使用業務的唯一字段作為主鍵。
顯然,主鍵長度越小,普通索引的葉子節點就越小,普通索引占用的空間也就越小.
面試
1.“N叉樹”的N值在MySQL中是可以被人工調整的么?
- 通過改變key值來調整
N叉樹中非葉子節點存放的是索引信息,索引包含Key和Point指針。Point指針固定為6個字節,假如Key為10個字節,那么單個索引就是16個字節。如果B+樹中頁大小為16K,那么一個頁就可以存儲1024個索引,此時N就等于1024。我們通過改變Key的大小,就可以改變N的值 - 改變頁的大小
頁越大,一頁存放的索引就越多,N就越大。
2.innodb B+樹主鍵索引的葉子節點存的是什么
- B+樹的葉子節點是page (頁),一個頁里面可以存多個行