數據庫索引爲何用B+樹實現?

爲何大多數數據庫索引都使用B+樹來實現呢?這涉及到數據結構、操做系統、計算機存儲層次結構等等複雜的理論知識,可是不用擔憂,這篇文章20分鐘以後就會給你答案。數據庫

這篇文章是一系列數據庫索引文章中的最後一篇,這個系列包括了下面四篇文章:編程

  1. 數據庫索引是什麼?新華字典來幫你 —— 理解緩存

  2. 數據庫索引融會貫通 —— 深刻數據結構

  3. 20分鐘數據庫索引設計實戰 —— 實戰post

  4. 數據庫索引爲何用B+樹實現? —— 擴展優化

這一系列涵蓋了數據庫索引從理論到實踐的一系列知識,一站式解決了從理解到融會貫通的全過程,相信每一篇文章均可以給你帶來更深刻的體驗。操作系統

爲何使用B+樹?

你們在數學課上必定據說過一個例子,在一堆已經排好序的數字當中找出一個特定的數字的最好辦法是一種叫「二分查找」的方式。具體的過程就是先找到這些數字中間的那一個數,而後比較目標數字是大於仍是小於這個數;而後根據結果繼續在前一半或者後一半數字中繼續查找。設計

這就相似於數據結構中的二叉樹,二叉樹就是以下的一種結構,樹中的每一個節點至多能夠有兩個子節點,而B+樹每一個節點則能夠有N個子節點。3d

image.png

這裏就不具體展開講解二叉樹了,咱們只須要知道,平衡的二叉樹是內存中查詢效率最高的一種數據結構就能夠了。指針

可是目前經常使用的數據庫中,絕大多數的索引都是使用B+樹實現的。那麼爲何明明是二叉樹查詢效率最高,數據庫中卻恰恰要使用B+樹而不是二叉樹來實現索引呢?

計算機存儲層次結構

image.png

計算機中的存儲結構分爲好幾個部分,從上到下大體能夠分爲寄存器、高速緩存、主存儲器、輔助存儲器。其中主存儲器,也就是咱們常說的內存;輔助存儲器也被稱爲外存,比較常見的就是磁盤、SSD,能夠用來保存文件。在這個存儲結構中,每一級存儲的速度都比上一級慢不少,因此程序訪問越上層存儲中的數據,速度就會越快。

有過編程經驗的小夥伴都知道,程序運行過程當中操做的基本都是內存,對外存中數據的訪問每每須要寫一些文件的讀取和寫入代碼才能實現。這正是由於CPU的計算速度比存儲的I/O速度(輸入/輸出速度)快不少所作的優化,由於CPU在每次計算完成以後就須要等待下一批的數據進入,這個等待的時間越短,計算機運行得越快。

因此對於數據庫索引來講,由於數據量很大,因此基本都是保存在外存中的,這樣的話數據庫讀取一個索引節點的成本就很是大了。在數據量同樣大的狀況下,咱們能夠知道,B+樹的單個節點中包含的值個數越多那麼樹中須要的節點總數就會越少,這樣查詢一次數據須要訪問的節點數就更少了。

若是你對B+樹還不熟悉,能夠到這篇文章中找到答案——數據庫索引融會貫通

若是咱們把二叉樹看作是特殊的B+樹(每一個節點只有一個值和先後兩個指針的B+樹),那麼就能夠得出結論:**由於B+樹的節點中包含的值個數(多個值)比二叉樹(1個值)更多,因此在B+樹中查詢所須要的節點數就更少。**那麼若是每次讀取的成本是同樣的話,由於總成本=讀取次數*單次讀取成本,咱們就能夠證實B+樹的查詢成本就比二叉樹小得多了。

節點讀取成本

可是咱們知道,讀取更多數據確定會須要更大的成本,那麼爲何數據庫索引使用B+樹仍是會比二叉樹更好呢?這就須要一些更高深的操做系統知識來解釋了。

在現代的操做系統中,把數據從外存讀到內存所使用的單位通常被稱爲「頁」,每次讀取數據都須要讀入整數個的「頁」,而不能讀入半頁或者0.8頁。一頁的大小由操做系統決定,常見的頁大小通常爲4KB=4096字節。因此無論咱們是要讀取1字節仍是2KB,最後都是須要讀入一個完整的4KB大小的頁的,那麼一個節點的讀取成本就取決於須要讀入的頁數。

在這樣的狀況下,若是一個節點的大小小於一頁的大小,那麼就會有一部分時間花在讀取咱們根本不須要的數據上(節點以外的數據),二叉樹在這方面就會浪費不少時間;而若是一個節點的大小大於一頁,哪怕是一頁的整數倍,那咱們也可能在一個節點的中間就找到了咱們須要的指針進入了下一級的節點,這樣這個指針後面的數據都白白讀取了,若是不須要這些數據可能咱們就能夠少讀幾頁了。

因此,綜上所述,數據庫索引使用節點大小剛好等於操做系統一頁大小的B+樹來實現是效率最高的選擇。

相關文章
相關標籤/搜索