MySQL InnoDB儲存引擎的B 樹索引演算法

2022-03-12 04:01:02 字數 2803 閱讀 1365

很早之前,就從學校的圖書館借了mysql技術內幕,innodb儲存引擎這本書,但一直草草閱讀,做的筆記也有些凌亂,趁著現在大四了,課程稍微少了一點,整理一下筆記,按照專題寫一些,加深一下印象,不枉讀了一遍書。與此同時,也加深一下對mysql的了解,認識了原理,對優化的原則才有把握,對問題的分析才有源頭。

①innodb儲存引擎支援兩種常見的索引。

一種是b+樹,一種是雜湊。b+樹中的b代表的意思不是二叉(binary),而是平衡(balance),因為b+樹最早是從平衡二叉樹演化來的,但是b+樹又不是乙個平衡二叉樹。

同時,b+樹索引並不能找到乙個給定鍵值的具體行。b+樹索引只能找到的是被查詢資料行所在的頁。然後資料庫通過把讀入記憶體,再在記憶體中進行查詢,最後得到查詢的資料。

先從二分查詢法說起:

二分查詢法的基本思想是,將記錄排序(假如從小到大排序),然後採用跳躍式的方式進行查詢,以有序數列的中點位置為比較物件,如果要找的元素小於該中點元素,那麼查詢左半部分,如果要找的元素大於該中點元素,那麼久找右半部分。比如一組排好序的數:5 10 19 22 30 55 59 60 90, 如果我要查詢60這個數字,那麼先找30,發現30小於60,那麼找30右半部分的中點59,發現59還是小了,那麼找59右邊的數,從而找到了60,這樣通過不斷二分把查詢需要的時間以指數級進行下降,演算法效率到了logn級別。

再說一下平衡二叉樹:

這是一幅平衡二叉樹,左子樹的值總是小於根的值,右子樹的值總是大於根的鍵值,因此可以通過中序遍歷(以遞迴的方式按照左中右的順序來訪問子樹),因此遍歷以後得到的輸出是9、17、28、35、39、56、65、87。這樣,如果要查詢鍵值為28的記錄,先找到根,然後發現根大於28,找左子樹,發現左子樹的根17小於28,再找下一層右子樹,然後找到28。通過了3次查詢找到了需要找的節點。但是如果二叉樹節點分布非常不均勻,就像第二張圖那樣,那麼如果要查詢39這個節點的話,查詢效率和順序查詢就差不多了,最差的結果就是查詢65,那麼二叉搜尋樹就會完全退化成線性表。因此如果想要最大效能地構造乙個二叉查詢樹,需要這顆二叉查詢樹是平衡的,平衡二叉樹對於查詢的效能是比較高的,但是不是最高的,只是接近最高的效能。要達到最好的效能,需要建立一顆最優二叉樹,但是最優二叉樹的建立和維護需要大量的操作,因此用平衡 二叉樹就比較好。同時,平衡二叉樹多用於記憶體結構物件中,因此維護他的開銷相對較小。

②為什麼使用b+樹呢?

雖然二叉查詢樹和平衡二叉樹都能夠實現較快的資料查詢,但是,由於資料庫的內容是存在於磁碟上,而磁碟io與記憶體io相比,比記憶體io慢了10^5~10^6倍,為了減少磁碟io,提高檢索速度,因而才用了b+樹這種資料結構。換言之,b+樹就是為磁碟或其他直接訪問輔助裝置而設計的一種多路查詢樹,是多叉樹

③什麼是b+樹,其特性是什麼

b+樹的概念還是過於複雜,直接上圖比較合適,來一張維基百科上的截圖:

從上面可以看出,所有記錄的節點都在頁節點中,並且是順序存放的,如果我們從最左邊的節點開始遍歷,可以得到的所有鍵值的順序是:1、2、3、4、5、6、7。

在b+樹中,所有記錄節點都是按照鍵值的大小順序存放在同一層的葉節點中,各個葉子節點通過指標進行連線。由於乙個節點中存放了多條的資料,那麼檢索的時候,進行的磁碟io次數將會少掉很多。

在b+樹插入的時候,為了保持平衡,對於新插入的鍵值可能需要做大量的拆分頁操作,而b+樹主要用於磁碟,因此頁的拆分意味著磁碟操作,因此應該在可能的情況下儘量減少頁的拆分。因此,b+樹提供了旋轉的功能。至於旋轉和刪除等內容,過於複雜,這篇筆記先不做記錄。只是了解使用b+樹的原因以及b+樹的特性。

innodb儲存引擎使用聚集索引,實際的資料行和相關鍵值儲存在一塊。因而,在innodb中要使用索引訪問資料始終需要兩次查詢,而不是一次。因為索引葉子節點中儲存的不是行的物理位置,而是主鍵的值。即:二次索引-->主鍵-->資料的葉子-->通過資料葉字節點中的page directory找到資料行。

因為每一張innodb的表都會有乙個主鍵索引,但是如果沒有顯式指定怎麼辦?如果沒有手工去指定主鍵索引的話,那麼,innodb引擎會指派乙個unique的列作為主鍵,如果沒有unique的字段的話,那麼便會自動生成乙個隱含的列作為主鍵。

所以,在在innodb的設計中,應該盡可能的使用乙個與業務無關auto_increment的自增主鍵,而不要去使用uuid之類的隨機(無序)的聚集鍵。同時,由於所有的索引都使用主鍵的索引,如果主鍵索引過長,也會使輔助索引相應的變大。

聚集索引的儲存並不是物理上的連續,而是邏輯上連續的。一方面,頁通過雙向鍊錶連線,頁按照主鍵的順序排列;另一方面,每個頁中的記錄也是通過雙向鍊錶進行維護,物理儲存上可以同樣不按照主鍵儲存。

對於目前的mysql來說,所有的對於索引的新增或者刪除操作,mysql資料庫都是要先建立一張新的臨時表,然後再把資料匯入臨時表,再刪除原來的表,然後再把臨時表命名為原來的表。所以,如果一張表中資料太多的話,那麼後期新增刪除索引需要花費很長的時間,因而最好在資料庫設計初期便設計好索引。

還有,雖然innodb儲存引擎從版本innodb plugin開始,支援一種稱為快速索引建立的方法,但是這種方法只限定於輔助索引,對於主鍵的建立和刪除還是需要重建一張表。

[1]敲**的張揚的《mysql索引背後的資料結構和演算法》

[2]《mysql技術內幕:innodb儲存引擎》

mysql InnoDB儲存引擎

innodb的組成部分 1.後台執行緒 2.儲存引擎記憶體池 innodb儲存引擎記憶體緩衝池 1.記憶體緩衝池 innodb是基於磁碟儲存的,並將其中的記錄按照頁的方式進行管理。因此,可將其視為基礎磁碟的資料庫系統。在資料庫系統中,由於cpu速度與磁碟速度之間的紅狗,基於磁碟的資料庫系統通常使用緩...

Mysql Innodb儲存引擎

鎖 參考資料 參考資料 行鎖 innodb的鎖是對索引加鎖,如果查詢到並沒有用到索引就會對錶進行加鎖 record lock 對單條記錄加上鎖 gap lock 間隙鎖,鎖定乙個範圍,但是不包含記錄本身 next key lock record lock gap lock,鎖定乙個方位並鎖定記錄本身...

MYSQL INNODB 儲存引擎

innodb 是事務安全的mysql儲存引擎,設計上採用了類似於oracle的架構。一般而言,在oltp的應用中,innodb應該作為核心應用表的首選儲存引擎。同時,也是因為innodb的存在,才使得mysql變得更有魅力。第一 innodb儲存引擎概述 innodb由innobase oy 公司開...