1. 程式人生 > >深入理解mysql資料庫B+樹索引

深入理解mysql資料庫B+樹索引

索引的作用:

首先索引通俗來講就像書的目錄,通過索引可以快速查詢對應資料,但這僅僅是表面上的,索引主要作用有3點,這僅僅算作其中1點。以下是鄙人的理解:

  1. 通過索引可以減少資料的掃描量(例如上面提到的將全書掃描,變成了根據目錄找)
  2. 索引可以把對硬碟的隨機IO變為順序IO()
  3. 索引可以在排序、分組等操作時避免建立臨時表()

詳細展開來:

mysql資料庫索引的資料結構是B+樹。什麼是B+樹

可以通過這篇部落格來了解 平衡二叉樹、B樹、B+樹

如果不是很瞭解樹的同學可以來到這裡視覺化構建樹,選擇對應的資料結構就可以了,我這裡的動圖也是從這來的。

上面部落格中對樹的概念講的比較詳細了,下面補充一下關於索引的選擇,mysql為什麼選擇B+樹(推薦與上面兩個連結一起閱讀):

為什麼不用簡單的二叉樹:

二叉樹存在著這麼樣一個弊端:在極端情況,他會成為一個連結串列,導致效能急劇下降。特製作一動圖供大家更好的理解:

 從動圖中可以看出,如果資料完全順序插入(比如索引的主鍵開啟了自增)會導致成為一個連結串列一樣的資料結構,查詢時候有可能演變為全表掃描,查詢動圖如下:

於是我們想把它優化一下,調整為平衡一點的二叉樹(葉子節點的高度差<=1)

平衡二叉樹動圖:

為什麼不使用平衡二叉樹(二路平衡查詢樹):

我們知道資料庫中是儲存資料的,資料量經常會達到百萬以上的級別,這時候的平衡二叉樹雖然解決了二叉樹的極限情況,但對於大資料來講,他的高度可能成百上千高度。

這裡補充一下資料庫有索引時查詢資料的過程

mspaint畫了個簡單的圖片,如果用平衡二叉樹儲存,假設主鍵索引儲存如下圖

如果要找主鍵為13的資料,需要把10經過磁碟IO讀到記憶體中,來對比,發現13>10,然後根據10的right值再進行一次IO拿到22,,對比發現13<22,然後根據22的left值再進行一次IO拿到13,發現13==13,則拿到4080,再從硬碟去讀。

這是軟體的過程,但我們知道,計算機底層是磁碟,磁碟IO是非常耗費時間的,而磁碟讀的時候一般是讀取4k的資料,我們一次IO讀取了4k資料(4k這裡大家自行補充硬體知識,玩過固態硬碟的朋友都知道4k應該,不知道的朋友自行百度,

點這裡可以檢視硬碟的底層原理),卻只拿到1個索引的值,這是非常不划算的,而且是非常慢的,因此,平衡二叉樹滿足不了我們對大資料的快速訪問。

總結平衡二叉樹不能作為索引的兩個主要原因:

  1. 高度太高                      導致IO次數太多
  2. 單節點儲存的資料個數太少       導致IO次數變多

解釋:不能很好地利用磁碟特性(一次讀4k ),也沒有利用到磁碟的預讀(關於磁碟IO點這裡

如果我們一次磁碟IO可以獲得多個索引的值,那效率就大大提高了,於是來到了B樹(多路平衡查詢樹)的概念。

(圖片來自部落格,圖僅供參考)

如果用B樹儲存A-Z則只需要3層即可,而平衡二叉樹則需要6層,這樣就減少了一般的IO次數,查詢效率翻倍

為什麼不用B樹(多路平衡查詢樹)

B樹相比平衡二叉樹大大減少了高度,也增加了單個節點上的數量,看起來已經非常不錯了,是的,但我們資料庫select操作時,很多時候不是select一條資料,而是多條資料,引來了B+樹的概念,如下

 

(圖片來源部落格)

B+樹和B樹相比,所有的資料只存在於葉子節點中,非葉子節點不儲存資料,且所有葉子節點為順序連結串列,以便掃描。

B樹的節點中存放了一定資料,B+樹的查詢區間為左閉右開區間,如上圖中查詢索引值為5的資料時,在根節點有三個區間:[5,28)[28,65)[65,∞),第一個區間包含5,但是非葉子節點不儲存資料地址,繼續往左找,來到[5,10)[10,20)[20,∞),繼續往左找來到葉子節點,發現有5,則找到。

B+樹對比B樹的優勢有:

  1. 擁有B樹的優勢
  2. 由於葉子節點的連結串列,掃表能力更強
  3. 節點的結構不同,磁碟讀寫能力更強
  4. 每次查詢都會來到葉子節點,磁碟IO時間固定,查詢效率穩定,準確統計和排查系統問題
  5. 排序能力更好

當然這些好處不是白來的,而是犧牲了不穩定的快速查詢(比如上述查詢5的例子提到的,B樹在根節點就返回了,而B+樹無論什麼索引值,都一定要到葉子節點才返回),但同樣因為這兒,也會能夠更準確統計和排查系統問題 。

點選這裡檢視博主其他部落格