B-trees

 B-trees

0d91e4e792fb936633033b38e57f28c8?s=128

tom--bo

July 10, 2020
Tweet

Transcript

  1. B tree実装してみた LT-slide (2020/07/10) @tom__bo

  2. 目次 • 目的 • B, B+, B* tree 整理 •

    (僕 )実装方針 • パフォーマンス比較 方法 • 現時点 実験結果 • 今後 課題
  3. 目的 Database Internals 輪読会に合わせて • 気になっていたB木, LSM木 比較をしたい • B木

    亜種も実装してみる • 勉強 ためにC++で書いてみる ◦ MySQLいじろうと思うと必須 ◦ C++まともに書いたことない (学生 頃、授業でC書いたくらいか?) • GitHub repo: https://github.com/tom--bo/trees
  4. B, B+, B*木 整理 • B tree ◦ アルゴリズムイントロダクション第 3版に詳細な実装例

    • B+ tree ◦ リーフノードだけにデータを持つ ◦ リーフノード同士 左右 リンクを持つ ◦ 提案論文? • B* tree ◦ 連続する2つ ノードがいっ いになったときに split(3つめを追加して2/3ずつ配分) ◦ 提案論文: BAYER, R., and MCCREIGHT, E. “Organization and maintenance of large ordered indexes.”, Acta Inf. 1, 1972, 173-189
  5. (僕 )実装方針 • Primary index as an Indirectionを想定 • key(Item.key)

    固定 • key 重複可, NULLなし • まず シングルスレッドで実装 • 各木 ◦ B tree : アルゴリズムイントロダクションを参考 ▪ https://github.com/tom--bo/trees/tree/5e4f5554ef239ef9af45d426e67ea1f0e3574899/btree ◦ B+ tree: B treeを独自で拡張 ▪ https://github.com/tom--bo/trees/tree/5e4f5554ef239ef9af45d426e67ea1f0e3574899/bplustree ◦ B* tree : B treeを独自で拡張 ▪ https://github.com/tom--bo/trees/tree/5e4f5554ef239ef9af45d426e67ea1f0e3574899/bstartree
  6. B tree 実装 • アルゴリズムイントロダクションを参考 ◦ RootからLeafに向けてノードをたどるときにノード 状態によって予め Split, Mergeする

    ◦ Merge 連続するノードが最低 key数にならない限り兄弟ノードから keyを移動する
  7. B+ tree 実装 • リーフノードにすべて Itemを持つ • 中間ノード Item そ

    右 子 sub-tree中 最小Item
  8. B* tree 実装 • 基本的に B tree • 連続する2ノードがいっ いになったらsplit

  9. パフォーマンス比較 方法 • ランダムにデータ生成 • ここで insert み 環境 •

    CPU: AMD Ryzen 9 3950X (16core 32threads) • OS: Ubuntu 19.10, Kernel: 5.3.0-61-generic • Clang: 9.0.0-2 (Compile: `clang++ -O2 … ` ) • ブログ: Ryzen 3950x でPC組んだ
  10. 結果(Node count) • 1,000,000 Insert keys後 ノード数 平均 (t =

    4, 8, 16, …, 512)
  11. 結果(Total time) • 1,000,000 Insert keys にかかった時間 平均 (t =

    4, 8, 16, …, 512)
  12. LRU cache • もっと現実的な(?)比較をしたい • LRU cacheで簡易的なbuffer_poolを実装 ◦ std::unordered_map, std::listを使ったシンプルな実装

    • アクセスしようとするノードがcacheになけれ ペナルティ(sleep 100us) ◦ dirty page(node) flushなどもあるが、adaptive flushingとか考え始めるときりがない
  13. 結果 (Node count with LRU cache) • 100,000 Insert keys

    (t = 64, 128 …, 512) • Cache size: 200 (nodes) ノード数 実行時間 キャッシュヒット率
  14. 今後やりたいこと • 実験 ◦ B, B+間で range scan比較 ◦ Read

    / write 比重を変化 ◦ LRUサイズ 変化 • 実装 ◦ 他 木: B-link tree, LSM tree, Skip list, (Masstree) ◦ UPDATE (?) • 各種最適化 ◦ 未定 • Thread-safe化 ◦ B-link tree以降で頑張る ◦ 現在 実装で root->leafへ 探索を再帰で書いていて大幅な修正が必要
  15. 疑問 • UPDATE 方法 ◦ 現状 Delete & Insertしか思いついていない ...

    • Thread-safe化 ◦ B-link tree以降で頑張る ◦ 現在 実装で root->leafへ 探索を再帰で書いていて大幅な修正が必要 • テスト 方法 ◦ 現状ランダムなテストケース作って ”対象 木”と”単純なHashMap” 両方に操作して最後に差分 がないか比較している ◦ B木 状態を理解してテストケースを作っていない ▪ コーナーケースを想定しきれずに早々に諦め