(DDIA)資料儲存與檢索(三) B tree

2021-09-10 22:38:37 字數 4305 閱讀 8694

目前我們所討論的日誌結構的索引已經被廣泛認可,但是他們卻不是最普遍的索引型別。被用於構建索引的最普遍的資料結構於此有很大的不同,我們稱之為:b-tree

在2023年引入,不到10年之後,已經發展到「無所不在」,b-trees經受住了時間的考驗。 它們仍然是幾乎所有關聯式資料庫中的標準索引實現,而且許多非關聯式資料庫也使用它們。

與sstables類似,b-tree將鍵值對按鍵排序,以便允許高效的鍵值查詢和範圍查詢,但二者僅有這一點相似之處,因為b-tree有非常不同的設計理念。

我們之前看到的日誌結構索引將資料庫分解為可變大小的 segments,通常是幾兆位元組或更大的大小,並且總是按順序寫。 與此相反,b-tree將資料庫分解成固定大小的塊或頁面,傳統上是4 kb大小(有時更大),並同時讀取或寫一頁。 這個設計更接近符合(corresponds )底層硬體,因為磁碟儲存也是採用類似的設計,資料被安排在固定大小的塊中。

b-tree中每個頁面都可以使用乙個位址或位置來標識,這允許乙個頁面轉到另乙個頁面(類似於乙個指標),注意這是在磁碟上而不是在記憶體中。 我們可以使用這些頁面引用來構建頁面樹,如所示。

一頁被指定為b-tree的root;每當你想要查詢索引中的key時,就從這裡開始。這個也包含幾個key和一些指向其子節點頁的指標。 每個子元素負責乙個連續的鍵範圍,引用之間的鍵表示這些範圍之間的界限在**。

在圖3-6的示例中,我們正在尋找key=251,因此我們知道我們需要遵循在邊界200和300之間的頁面引用。 這就把我們進一步引入200-300範圍分解的子範圍。

最終,我們會找到乙個包含單個key(葉子頁)的頁面,其中包含每個key的值,或者包含指向該值的頁面的引用。

在b-tree的一頁中對子頁面的引用數量稱為分支因子(branching  factor)。例如,在圖3-6中,分支因子為6。在實踐中,分支因素取決於儲存頁面所需的空間數量和範圍邊界,但通常是幾百個

如果您想要更新b-tree中的現有key的值,則需要搜尋包含該key的頁,更改該頁面中的值,並將該頁面寫回磁碟(任何對該頁面的引用仍然有效), 如果您想新增乙個新key,您需要找到其範圍包含新key的頁面並將其新增到該頁面中。 如果頁面中沒有足夠的空閒空間來容納新key,那麼它切分成兩個完整的頁面,而父頁面將被更新,如圖3-7( 將乙個新key插入到b-tree中是相當直觀的,但是刪除乙個key(同時保持樹的平衡)會更複雜一些[2])。

[上傳失敗…(image-bd0a82-1550122280516)]

這個演算法保證了樹的平衡:乙個b -樹,n個鍵,alwayshas a depth of o(log n),大多數資料庫都能適應b-tree,它有3到4個級別,所以你不需要遵循很多頁面引用來找到你要查詢的頁面。(4kb頁的四層樹,其分支係數為500,可儲存到256 tb(即500^4*4k)。)

b-tree底層基本的寫操作是用新的頁面資料覆蓋磁碟上的乙個頁面,我們先假定覆蓋寫操作不會改變頁面的位置,例如; 當頁面被覆蓋時,所有對該頁面的引用都保持不變。 這與lsm -tree這樣的日誌結構索引形成了鮮明的對比:這些索引只會附加到檔案(最終會刪除過時的檔案),但永遠不會修改檔案。

您可以考慮將磁碟上的頁面重寫看做為實際的硬體操作。 在磁碟上,這意味著把磁碟頭移到正確的位置,然後用新的資料覆蓋適當的扇區。 在ssd上,由於ssd必須在一段時間內清除和重寫相當大的一段電晶體晶元[19],所以會發生一些更複雜的情況。

此外,有些操作需要覆蓋多個不同的頁面。 例如,因為插入它的內容過多導致需要分割乙個頁面 ,那麼您需要將兩個頁面分開,並覆蓋它們的父頁面,同時更新兩個子頁面的內容。 這是乙個危險的操作,因為如果資料在僅僅一些頁面被寫入後崩潰了,那麼您最終會得到乙個cor - rupted索引(例如,可能會有乙個孤兒頁面,而不屬於任何父頁面)。

更新頁面的另乙個複雜之處是,如果多個執行緒在同一時間訪問b-tree,則需要進行嚴密的併發控制,否則執行緒可能會在不一致的狀態下看到b-tree中的資料。 這通常是通過使用鎖 (輕量級鎖)來保護樹的資料結構的。 在這方面,日誌結構的方法比較簡單,因為它們在後台進行所有合併,而不會干擾正常的查詢,並且不時地將新segments與老的segments進行原子操作的交換。

由於b-tree已經存在了很長時間,所以許多優化技術在過去的幾年裡發展起來也就不足為奇了。僅舉幾個例子:

儘管b-tree實現通常比lsm-tree實現更成熟,但lsm樹的特性也很有用。根據經驗lsm-tree通常對寫操作支援更友好,寫操作更快,而b-trees被認為讀起來更快[23],在lsm-trees上讀取通常要慢一些,因為它們必須檢查不同的壓縮階段的資料結構和sstables。

但是,基準測試通常對工作負載的細節並不十分不確定。你需要使用你的特定工作負載來測試系統,以便獲得更為準確的測試結論。 在本節中,我們將簡要討論一些在度量儲存引擎效能時值得考慮的事情。

b-tree索引至少需要寫兩次資料:一次是寫日誌(write-ahead log),一次是樹頁面本身(可能是頁面分割後)。 同時即使頁面中只有幾個位元組發生了變化也需要對整個頁面進行重寫。 有些儲存引擎甚至會在相同的頁面上重寫兩次,以避免在出現電源故障時出現部分更新的頁面[24,25].。

由於重複的壓縮和sstables的合併,日誌結構的索引也需要多次重寫資料。 這個中多次寫入資料庫,導致在資料庫的生命週期中對磁碟進行多寫操作—稱為write amplification。 當使用ssd時就需要特別注意,ssd是有寫入次數的,所以在使用ssd時只能覆寫固定的塊,即這些塊的寫入次數還沒有被耗盡。

在哪些需要對資料庫進行大量寫操作的應用程式中,效能瓶頸可能是資料庫寫入磁碟的速率。 在這種情況下,write amplification有乙個直接的效率成本:在可用的磁碟頻寬內,乙個儲存引擎寫入磁碟的次數越多,每分鐘內處理寫入的將越少 。

此外,lsm-tree通常能夠比b-tree保持更高的寫吞吐量,一部分原因是它們有時具有更低的寫擴增(儘管這取決於儲存引擎的配置和工作負載),另一部分原因是它們可以順序地寫sstable檔案,而不是在樹中重寫幾個頁面[26]。 這種差異在磁碟上尤其重要,因為在磁碟上,順序寫入比隨機寫入要快得多。

lsm-tree可以被更好地壓縮,因此他們在磁碟上生成的檔案通常要比b-tree生成的檔案更小。b-tree儲存引擎會存在磁碟碎片化的問題;當乙個頁面被分割,或者當乙個行不能儲存在現有的頁面時,頁面中的一些空間就無法被使用,一致處於空餘狀態。 由於lsm-tree不是面向頁的,並且周期性地重寫sstables以清除碎片,所以在使用分層壓縮[27]時,它們的儲存開銷更低。

在許多ssd中,韌體內部使用一種日誌結構演算法來將隨機寫轉化為順序寫,因此儲存引擎寫入模式對此影響不那麼顯著[19] 。但是,較低的write amplification和較少儲存碎片對ssd仍然是有利:資料的儲存更加緊湊,在可用的i/o 頻寬中可以滿足更多的讀寫請求。

日誌結構儲存的缺點是壓縮過程有時會影響(interfere  with)正在進行的讀和寫的效能。 即使儲存引擎試圖逐步執行壓縮操作以便盡量不影響併發訪問。但是,畢竟磁碟資源有限,仍然很容易發生這樣的情況:當磁碟完成乙個昂貴的壓縮操作時,請求(讀請求和寫請求)操作需要等待。在進行延遲監控時,這種情況雖然對吞吐量和平均響應時間的影響通常很小,但在較高的佔位百分比數值中,日誌結構儲存引擎的查詢響應時間有時相當高,而b-tree相對而言則可以更容易**和監測[28]

壓縮的另乙個問題是高寫吞吐量:有限的磁碟寫入頻寬需要在初始寫入(日誌資料寫入資料庫和重新整理memtable到磁碟)和後台執行的壓縮執行緒之間共享。 當寫入乙個空資料庫時,可以使用整個磁碟頻寬來進行初始寫入,但是資料庫中資料量越大,壓縮所需的磁碟頻寬就越多。如果寫吞吐量高,而壓縮程序沒有經過優化配置,則會發生壓縮無法跟上寫入速度的情況。 在這種情況下,磁碟上未合併的segment的數量一直在增長,直到耗盡磁碟空間,並且讀取速度也會減慢,因為它們需要檢查更多的segment檔案。 通常,即使後台執行的壓縮程序不能保持較高的壓縮效率,基於sstable的儲存引擎也不會限制資料寫入的速度,因此需要提供額外的監視來檢測這種情況[29,30]。

b-tree的乙個優點是,每個key在索引中只儲存在乙個位置,而乙個日誌結構的儲存引擎可能有多個相同的key且這些key在不同的segment中。b-tree資料庫希望提供強大的事務語義,這就使得它很具有吸引力:在許多關聯式資料庫中,事務隔離是在key的範圍內使用鎖實現的,在b-tree索引中,這些鎖掃瞄直接連線到樹[5]。在第七章,我們將更詳細地討論這一點。

b-tree在資料庫體系結構中是根深蒂固的,並且在許多任務作負載中提供良好的一致性,所以它們不可能短時間內消失掉。 在新的資料儲存中,日誌結構的索引變得越來越流行。並沒有任何快速簡單的規則來確定哪種型別的儲存引擎對您的用例更好,這需要憑藉自身經驗和對自身業務的認知進行測試。

未完待續。。。。

(DDIA)資料儲存與檢索(一)

乙個資料庫最基本的要具有兩個功能 當你給它一些資料的時候它可以幫你儲存資料,之後當你需要這些資料時,他可以返回給你所需要的資料。你 應用程式開發人員 向資料庫提供固定格式的資料,稍後你就可以再次請求獲取這些資料。在本章中,我們將從資料庫的角度討論以下問題 資料庫如何儲存我們所給出的資料,以及當我們需...

DDIA讀書筆記 3 資料儲存與檢索

構建和維護sstables 如何避免資料庫崩潰時,在記憶體中的記憶體表資料丟失?lsm儲存引擎 log structured merge tree 基於合併和壓縮進序檔案原理的儲存引擎 lsm補充 lucene中,從詞條到posting list的對映關係儲存在類sstable的排序檔案中,這些檔案...

關於資料的儲存與檢索

1.儲存資料的兩種方式 普通檔案 flat file 和資料庫 2.php中開啟檔案用放fopen 函式 do cume ntro ot server document root php內建變數 fp fop en document root orders orders.txt w 第二個引數為檔案...