B-epsilon Trees: Bridging the Gap Between B+ Trees and LSM-Trees

In storage engine design, systems face a classic dilemma known as the Optimal Trade-Off Curve for Dictionary Operations. B+ Trees deliver fast point reads and immediate range queries (O(log_B N) I/Os) but suffer from random disk writes (requiring up to 1 I/O per write). Conversely, LSM-Trees provide fast sequential writes (O(1/B) I/Os) but incur high read amplification when reconciling multiple SSTable layers.

Introduced by Michael A. Bender et al., the B-epsilon Tree (and its industrial implementation, the Fractal Tree) resolves this dichotomy. By adding dedicated message buffers to every internal node, B-epsilon trees achieve asymptotically optimal write throughput while preserving standard B+ Tree point read and range scan performance.

Node Architecture and the Epsilon Parameter

A B-epsilon tree node of block size B allocates its internal memory budget between two components parameterized by a tuning factor epsilon (where 0 <= epsilon <= 1):

  • Pivot Keys and Child Pointers: A fraction of node space (B^epsilon) is dedicated to storing routing keys and child pointers, dictating the tree's branching fan-out.
  • Node Message Buffers: The remaining majority of the node space (B - B^epsilon) is allocated to a pending message buffer that stores uncommitted insert, update, and delete operations.
  • Tuning Extremes: When epsilon = 1, the buffer space vanishes, degenerating the structure into a classic B+ Tree. When epsilon = 0, node capacity is entirely buffer space, mirroring an LSM-Tree.

Core Operations: Buffered Down-Sweeping

1. The Buffered Write Path (Inserts, Updates, Deletions)

When a write arrives, the storage engine appends a message (e.g., `INSERT(key, val)` or `DELETE(key)`) exclusively to the root node's message buffer. Once appended to the root buffer, the write operation returns immediately without descending deeper into the tree.

2. Buffer Flushing (The Down-Sweep)

When an internal node's buffer fills to capacity:

  1. Identify the child node that is the destination for the largest batch of pending messages in the buffer.
  2. Flush that contiguous batch of messages down to that specific child's buffer in a single batched disk I/O.
  3. If the child node is a leaf, apply the mutations directly to data records.
  4. If the child node is an internal node and its buffer overflows as a result, recursively trigger a flush down to its children.

3. The Point Read Path

To read a key, traverse the tree from root to leaf just like in a B+ Tree. Along the path, inspect the message buffers of all visited internal nodes and combine any pending mutations with the record found at the leaf page.

Algorithmic Complexity & Storage Comparison

  • Write Cost: B-epsilon Trees write in O((1 / (B^(1-epsilon))) * log_B N) I/Os per operation—orders of magnitude faster than standard B+ Trees because writes are aggregated and flushed in large batches.
  • Read Cost: Point queries take O(log_B N) I/Os, exactly matching the height-bounded point lookup cost of a B+ Tree.
  • Range Scan Cost: Once the start key is reached, leaf pages provide direct sequential access with zero multi-layer merge overhead.
  • No Global Compaction: Unlike LSM-Trees which periodically trigger heavy background compaction phases that saturate I/O channels, B-epsilon trees flush localized buffers along individual branches.

Real-World Systems Applications

  1. TokuDB Storage Engine (MySQL / MariaDB): Utilizes Fractal Tree indexing to deliver high-throughput transactional writes and continuous indexing on active tables without degrading read latency.
  2. TokuMX (MongoDB Variant): Replaces WiredTiger B-Trees with Fractal Trees to accelerate high-volume document ingestion workloads and index builds.
  3. BetrFS (Write-Optimized Linux File System): A kernel-level copy-on-write filesystem using B-epsilon trees for filesystem metadata and data storage, achieving high small-file write throughput.
  4. High-Frequency Time-Series Archival: Serving real-time telemetry streaming platforms where writes outnumber point lookups by orders of magnitude while maintaining ad-hoc query capabilities.