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:
- Identify the child node that is the destination for the largest batch of pending messages in the buffer.
- Flush that contiguous batch of messages down to that specific child's buffer in a single batched disk I/O.
- If the child node is a leaf, apply the mutations directly to data records.
- 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
- 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.
- TokuMX (MongoDB Variant): Replaces WiredTiger B-Trees with Fractal Trees to accelerate high-volume document ingestion workloads and index builds.
- 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.
- 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.