Skip to content

Buffer Tree

buffer tree · 缓冲树

在高扇出树节点积累操作并批量下推,以排序量级 I/O 支持批量动态操作。

条目类型
模型

形式陈述

结构

在参数为 (M,B)外存模型中,以B-tree式高扇出层级为骨架,取扇出 Θ(M/B) 的多路树。每个内部节点除分隔键外还维护可容纳 Θ(M) 条操作的缓冲;新 insert/delete/search 请求先写入根缓冲,不立即沿路径执行。叶保存键或最终操作结果。

Flush 不变量

缓冲满时,把其中 Θ(M) 条操作按目标孩子分组,并以顺序块写入各孩子缓冲;一次 flush 读写 O(M/B) 块,平均每条操作 O(1/B) I/O。每条操作向下经过

O(logM/B(N/B))

层,所以批量操作的摊还 I/O 为 O((1/B)logM/B(N/B)),总量达到 Sort 级别。结束前必须 drain 所有缓冲,未下推操作仍是逻辑状态的一部分。

直觉

外存访问的昂贵单位是一整块,而不是一次比较。Buffer Tree 故意推迟单条操作,让同一路径方向上的请求先凑成能填满许多块的批次,再顺序下推;延迟换来的不是更短的树高,而是让一次 I/O 同时为大量操作服务。

操作分组与批量下刷
例子与边界

批量插入例子

日志索引连续收到数百万条插入。逐条 B-tree 查询会为每条记录访问一条根叶路径;buffer tree 先在根聚合,按键区间成批分给子树,让一次读入的块处理许多记录。重复键的 insert/delete 顺序需在缓冲内保留时间戳,不能简单相消后改变语义。

查询与边界

单个 point query 可能要检查根到叶路径上尚未 flush 的所有缓冲,延迟并非普通 B-tree 的简单 O(logBN)。结构优化的是 batched/摊还 I/O,不是数据库 buffer pool,也不保证每次更新最坏便宜。缓冲容量、扇出和内存内分组算法必须共同满足 M 约束;flush 若对每个孩子随机写小片段,会丢失块效率。

操作排序与正确性

同一键的更新可能同时位于祖先和后代缓冲。下推时应按时间戳稳定排序,或先按键分组再折叠成等价净操作,确保较晚 delete 不被较早 insert 覆盖。批量 search 可作为带时间戳操作一路下推,在叶与此前更新合并后输出。

一次 flush 的内存内排序是否免费取决于 I/O 模型:CPU 免费但 Θ(M) 项必须已在内存;若缓冲超过 M 就不能一次分组。最终报告结果前 drain 的 I/O 也属于总批处理成本。

推论与应用

Buffer Tree 把一批更新攒满后向下刷新,单次 flush 很贵;摊还分析按每个元素穿过的树层收费,证明总 I/O 而非每次操作的即时 I/O。

一次 flush 的操作次序

根缓冲满时,先按目标孩子对操作稳定分组;对同一键的多条操作再按时间排序,必要时合并 insert-delete 对或保留最后写。每组以连续 I/O 写入对应孩子缓冲,孩子溢出则递归 flush。先按键排序却丢掉时间序,会让较旧删除覆盖较新插入。

一次 flush 移动 Θ(M) 条操作,向 Θ(M/B) 个孩子各付常数块 I/O,总计 Θ(M/B) 次。因此每条操作每下降一层摊到 O(1/B) I/O,树高为

O(logM/BNB),

批量更新摊还为该高度除以 B。这个界依赖缓冲确实批满后再写;若每来一条就随机写子节点,批处理优势消失。

点查询要沿根到叶检查所有尚未下推的缓冲,并按时间合成同键操作,不能只查叶。Buffer Tree 因而主要优化批量吞吐,不保证单次查询或更新的低尾延迟。

参考资料
  • Lars Arge, The Buffer Tree: A New Technique for Optimal I/O Algorithms, WADS, 1995.
  • Jeffrey Vitter, External Memory Algorithms and Data Structures, ACM Computing Surveys, 2001.
关系图谱6 个相邻概念 · 2 类关系

拖动节点调整位置。

显示关系

显示:依赖

  1. 前置三跳
  2. 前置二跳
  3. 前置一跳
  4. 当前条目
  5. 后续一跳
  6. 后续二跳
  7. 后续三跳
文字版关系按与当前条目的最短距离分组
类型化关系

使用的工具