【Java面试题】MySQL索引底层为什么用到B+树
學習本章之前,先要了解紅黑樹【算法】紅黑樹原理和算法介紹,以及B樹、B+樹【算法】B樹、B+樹詳解
最近重新學習MySQL,發現自己一直知道MySQL索引用到了B+樹,引發思考,為什么一定要是B+樹,其他樹或者其他數據結構不可以嗎?
為什么不是用紅黑樹
1、將大量數據全部放入內存組織成RBT結構顯然是不實際的。實際上,像OS中的文件目錄存儲,數據庫中的文件索引結構的存儲…. 都不可能在內存中建立查找結構。數據必須在磁盤中建立好這個結構。
2、這就涉及到磁盤的存儲原理了,操作系統讀寫磁盤的基本單位是扇區,而文件系統的基本單位是簇(Cluster)(每個簇或者塊可以包括2、4、8、16、32、64…2的n次方個扇區。)。意思就是,磁盤讀寫有一個最少內容的限制,即使我們只需要這個簇上的一個字節,我們也必須把整個簇的內容都讀完,那么現在就有一個悲催的事情了,如果一個父節點只有2個子結點,并不能填滿一個簇上的所有內容,那多余的地方就浪費了,考慮到磁盤的存儲原理,B/B+樹應運而生了。
3、由于B/B+樹分支比二叉樹多,所以相同數量的內容,B+樹的深度更淺。B+樹的深度就代表了磁盤的 I/O 次數。
4、數據庫設計的時候B+樹有多少個分支都是按照磁盤上一個簇最多能放多少節點設計的,因此一般來說,涉及到磁盤上查詢的數據結構,都是使用B/B+樹
為什么說B+樹比B樹更適合數據庫索引?
1)B+樹的磁盤讀寫代價更低
B+樹的內部結點并沒有指向關鍵字具體信息的指針。因此其內部結點相對B 樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那么盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的需要查找的關鍵字也就越多。相對來說IO讀寫次數也就降低了;
2)B+樹查詢效率更加穩定
由于非終結點并不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當;
3)B+樹便于范圍查詢(最重要的原因,范圍查找是數據庫的常態)
B樹在提高了IO性能的同時并沒有解決元素遍歷的我效率低下的問題,正是為了解決這個問題,B+樹應用而生。B+樹只需要去遍歷葉子節點就可以實現整棵樹的遍歷。而且在數據庫中基于范圍的查詢是非常頻繁的,而B樹不支持這樣的操作或者說效率太低;
磁盤IO與預讀
計算機存儲設備一般分為兩種:內存儲器(main memory)和外存儲器(external memory)。
內存儲器為內存,內存存取速度快,但容量小,價格昂貴,而且不能長期保存數據(在不通電情況下數據會消失)。
外存儲器即為磁盤讀取,磁盤讀取數據靠的是機械運動,每次讀取數據花費的時間可以分為尋道時間、旋轉延遲、傳輸時間三個部分,尋道時間指的是磁臂移動到指定磁道所需要的時間,主流磁盤一般在5ms以下;旋轉延遲就是我們經常聽說的磁盤轉速,比如一個磁盤7200轉,表示每分鐘能轉7200次,也就是說1秒鐘能轉120次,旋轉延遲就是1/120/2 = 4.17ms;傳輸時間指的是從磁盤讀出或將數據寫入磁盤的時間,一般在零點幾毫秒,相對于前兩個時間可以忽略不計。那么訪問一次磁盤的時間,即一次磁盤IO的時間約等于5+4.17 = 9ms左右,聽起來還挺不錯的,但要知道一臺500 -MIPS的機器每秒可以執行5億條指令,因為指令依靠的是電的性質,換句話說執行一次IO的時間可以執行40萬條指令,數據庫動輒十萬百萬乃至千萬級數據,每次9毫秒的時間,顯然是個災難。下圖是計算機硬件延遲的對比圖,供大家參考:
考慮到磁盤IO是非常高昂的操作,計算機操作系統做了一些優化,當一次IO時,不光把當前磁盤地址的數據,而是把相鄰的數據也都讀取到內存緩沖區內,因為局部預讀性原理告訴我們,當計算機訪問一個地址的數據的時候,與其相鄰的數據也會很快被訪問到。每一次IO讀取的數據我們稱之為一頁(page)。具體一頁有多大數據跟操作系統有關,一般為4k或8k,也就是我們讀取一頁內的數據時候,實際上才發生了一次IO,這個理論對于索引的數據結構設計非常有幫助。
事實1 : 不同容量的存儲器,訪問速度差異懸殊。
磁盤(ms級別) << 內存(ns級別), 100000倍
若內存訪問需要1s,則一次外存訪問需要一天
為了避免1次外存訪問,寧愿訪問內存100次...所以將最常用的數據存儲在最快的存儲器中
事實2 : 從磁盤中讀 1 B,與讀寫 1KB 的時間成本幾乎一樣
從以上數據中可以總結出一個道理,索引查詢的數據主要受限于硬盤的I/O速度,查詢I/O次數越少,速度越快,所以B樹的結構才應需求而生;B樹的每個節點的元素可以視為一次I/O讀取,樹的高度表示最多的I/O次數,在相同數量的總元素個數下,每個節點的元素個數越多,高度越低,查詢所需的I/O次數越少;假設,一次硬盤一次I/O數據為8K,索引用int(4字節)類型數據建立,理論上一個節點最多可以為2000個元素,2000*2000*2000=8000000000,80億條的數據只需3次I/O(理論值),可想而知,B樹做為索引的查詢效率有多高;
另外也可以看出同樣的總元素個數,查詢效率和樹的高度密切相關
總結
以上是生活随笔為你收集整理的【Java面试题】MySQL索引底层为什么用到B+树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JVM相关问题
- 下一篇: lol猪妹s11出装 瑟庄妮打野天赋