1. 程式人生 > >InnoDB儲存引擎B+樹索引介紹

InnoDB儲存引擎B+樹索引介紹

一、InnoDB索引概述:

InnoDB儲存引擎支援B+樹索引、雜湊索引、全文索引和空間索引,後兩種很少用到,本文主要介紹B+樹索引。

B+樹是從最早的平衡二叉樹(AVL)演變而來,但是B+樹不是一個二叉樹。B+中的B不代表二叉(Binary),而是代表平衡(Balance)。其他常見的樹結構還有BST,紅黑樹,B樹,B*樹。

MySQL中的B+樹索引可以分為聚集索引(clustered index)和非聚集索引(non-clustered index)。

InnoDB聚集索引就是按照每張表的主鍵構造一顆B+樹,並且葉子節點上存放著整行記錄資料,而非聚集索引的葉子節點上僅儲存鍵值以及指向資料頁的偏移量。聚集索引的這個特性決定了索引組織表中資料也是索引的一部分。(ps:MyISAM索引的葉子節點上存放的是資料記錄的地址。)

二、B+樹索引結構

B+樹是為磁碟及其他儲存輔助裝置而設計一種平衡查詢樹(不是二叉樹)。B+樹中,所有記錄的節點按大小順序存放在同一層的葉子節點中,各葉子節點用指標進行連線。MySQL將每個葉子節點的大小設定為一個頁的整數倍,利用磁碟的預讀機制,能有效減少磁碟I/O次數,提高查詢效率。

頁是計算機管理儲存器的邏輯塊,硬體及OS往往將主存和磁碟儲存區分割為連續的大小相等的塊,每個儲存塊稱為一頁,頁的大小通常為4K。

下圖,是一個經典的B+樹組織結構圖(簡化的2層B+樹,每個頁面的扇出為4):


此B+樹,有5條使用者記錄,分別是1,2,3,4,5;

B+樹上層頁面中的記錄,儲存的是下層頁面中的最小值(Low Key);

B+樹的所有資料,均儲存在B+樹的葉節點;

B+樹葉子節點的所有頁面,通過雙向連結串列連結起來;

關於B+樹的分裂與合併,這裡不作詳細介紹,有興趣的可以自行了解。

實際上B+索引在資料庫中有一個特點就是其高扇出性,因此在資料庫中,B+樹的高度一般不超過3層,也就是對於查詢某一鍵值的行記錄,最多隻需要2到3次IO。現在一般的機械硬碟的IOPS在100~200之間,2~3次的IO意味著查詢時間只需0.02~0.03秒,更有甚者,現在大多數企業都使用SSD固態硬碟,IOPS基本超過50000,查詢效率進一步提升。

所有的葉子節點使用指標連結的好處是可以進行區間訪問,這也是MySQL使用B+樹作為索引儲存結構的重要原因。

另一個重要的問題,為什麼通常我們要給表設定一個自增的主鍵,因為所有記錄的節點按大小順序存放在同一層的葉子節點中,這樣就就會形成一個緊湊的索引結構,近似順序填滿,每次插入新資料時減少B+樹維護的成本。如果使用非自增主鍵,由於每次插入主鍵的值近乎於隨機,分裂會造成了大量的碎片,後續不得不通過OPTIMIZE TABLE來重建並優化填充頁面。另外區間讀取時,MySQL預讀一部分和你當前讀資料所在記憶體相鄰的資料塊,也能有效減少磁碟I/O次數。

B+樹索引並不能找到一個鍵值對應的具體行。b+樹索引只能查到被查詢資料行所在的頁,然後資料庫通過把頁讀入記憶體,再在記憶體中查詢,最後得到結果。

三、什麼是順序讀和隨機讀

順序讀是指順序的讀取磁碟上的塊,隨機讀是指訪問的塊是不連續的,需要磁碟的磁頭不斷移動。隨機讀的效能是遠遠低於順序讀的。在資料庫中,順序讀根據索引的葉節點就能順序的讀取所需的行資料,這個順序讀只是邏輯的順序讀,在磁碟上可能還是隨機讀。

隨機讀是指訪問輔助索引葉節點不能完全得到結果,需要根據輔助索引頁節點中的主鍵去尋找實際資料行。對於一些取表裡很大部分資料的查詢,正式因為讀取是隨機讀,而隨機讀的效能會遠低於順序讀。所以優化器才會選擇全部掃描順序讀,而不使用索引。

InnoDB儲存引擎有兩個預讀取方法,隨機預讀取線性預讀取。隨機預讀取是指當一個區(共64個連續頁)中有13個頁在緩衝區中並被頻繁訪問時,InnoDB儲存引擎會將這個區中剩餘的頁預讀到緩衝區。線性預讀取基於緩衝池中頁的訪問方式,而不是數量。如果一個區中有24個頁被順序訪問了,則InnoDB會讀取下一個區的所有頁到緩衝區。但是InnoDB預讀取經過測試後效能比較差,經過TPCC測試發現禁用預讀取比啟用預讀取提高了10%的效能。在新版本InnoDB中,MySQL禁用了隨機預讀取,僅保留了線性預讀取,並且加入了innodb_read_ahead_threshold引數,當連續訪問頁超過該值時才啟用預讀取,預設值為56。

四、B+樹索引的使用

MySQL索引的新增和刪除操作,對於主鍵索引,MySQL先是建立一張加好索引的臨時表,然後把資料匯入臨時表,再刪除原表,把臨時表重新命名為原表。對於二級索引,新版本的MySQL不再建立臨時表,而是首先對錶加S鎖,在建立的過程中不需要重建表,但是由於上了S鎖,在建立索引的過程中只能進行查詢操作,不能更新資料。

低選擇性的欄位沒有必要新增B+樹索引。例如性別,它們取值範圍很小。相反,某個欄位取值範圍很廣,如姓名,幾乎沒有重複,即高選擇性,則使用B+索引是比較合適的。

五、聯合索引

聯合索引還是一個B+樹,不同的是記錄節點的鍵值數量不是1,而是大於等於2,並按順序排列,所以聯合索引才會有最左匹配原則。