MySQL索引背后的數據結構及算法原理
https://www.kancloud.cn/kancloud/theory-of-mysql-index 非常好
根據一條sql 如何查看索引結構等信息?
聚簇索引
數據庫表中的數據都是存儲在頁里的,那么這一個頁可以存放多少條記錄呢?
這取決於一行記錄的大小是多少,假如一行數據大小是1k,那么理論上一頁就可以放16條數據。
當然,查詢數據的時候,MySQL也不能把所有的頁都遍歷一遍,所以就有了索引,InnoDB存儲引擎用B+樹的方式來構建索引。
聚簇索引就是按照每張表的主鍵構造一顆B+樹,葉子節點存放的是整行記錄數據,在非葉子節點上存放的是鍵值以及指向數據頁的指針,同時每個數據頁之間都通過一個雙向鏈表來進行鏈接。
如上圖所示,就是一顆聚簇索引樹的大致結構。它先將數據記錄按照主鍵排序,放在不同的頁中,下面一行是數據頁。上面的非葉子節點,存放主鍵值和一個指向頁的指針。
當我們通過主鍵來查詢的時候,比如id=6的條件,就是通過這顆B+樹來查找數據的過程。它先找到根頁面(page offset=3),然后通過二分查找,定位到id=6的數據在指針為5的頁上。然后進一步的去page offset=5的頁面上加載數據。
在這里,我們需要理解兩件事:
上圖中B+樹的根節點(page offset=3),是固定不會變化的。只要表創建了聚簇索引,它的根節點頁號就被記錄到某個地方了。還有一點,B+樹索引本身並不能直接找到具體的一條記錄,只能知道該記錄在哪個頁上,數據庫會把頁載入到內存,再通過二分查找定位到具體的記錄。
現在我們知道了InnoDB存儲引擎最小存儲單元是頁,在B+樹索引結構里,頁可以放一行一行的數據(葉子節點),也可以放主鍵+指針(非葉子節點)。
上面已經說過,假如一行數據大小是1k,那么理論上一頁就可以放16條數據。那一頁可以放多少主鍵+指針呢?
假如我們的主鍵id為bigint類型,長度為8字節,而指針大小在InnoDB源碼中設置為6字節。這樣算下來就是 16384 / 14 = 1170,就是說一個頁上可以存放1170個指針。
一個指針指向一個存放記錄的頁,一個頁里可以放16條數據,那么一顆高度為2的B+樹就可以存放 1170 * 16=18720 條數據。同理,高度為3的B+樹,就可以存放 1170 * 1170 * 16 = 21902400 條記錄。
理論上就是這樣,在InnoDB存儲引擎中,B+樹的高度一般為2-4層,就可以滿足千萬級數據的存儲。查找數據的時候,一次頁的查找代表一次IO,那我們通過主鍵索引查詢的時候,其實最多只需要2-4次IO就可以了。
那么,實際上到底是不是這樣呢?我們接着往下看。
————————————————
版權聲明:本文為CSDN博主「Java大楊」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/weixin_49723683/article/details/110958312