Why Do B+ Trees Use Linked Leaf Nodes for Range Queries?
B+ trees store all data records in linked leaf nodes to minimize disk I/O operations and maximize cache locality during sequential range queries. By separating routing keys in internal nodes from actual data in the leaves, a B+ tree achieves a higher branching factor and shallower tree height. Once a search locates the starting key in a leaf node, the linked list structure allows the system to scan subsequent records sequentially without traversing back up and down the tree.
Separation of Routing Keys and Data Records
In a standard B-tree, internal nodes store both keys and pointers to data records (or the records themselves). Because each node has a fixed size—typically aligned with a disk page or block of size \(B\)—storing data payloads inside internal nodes reduces the number of keys and child pointers a single node can hold.
A B+ tree removes data records from internal nodes entirely, keeping only routing keys and child pointers. If a key has size \(k\) and a child pointer has size \(p\), an internal node of size \(B\) can hold a fanout (branching factor) of approximately:
\[m \approx \left\lfloor \frac{B}{k + p} \right\rfloor\]
Because \(m\) is much larger in a B+ tree than in a B-tree, the height of the tree, \(h = O(\log_m N)\) for \(N\) records, is significantly smaller. A shallower tree means fewer page reads are required to reach the leaf level for any initial lookup.
How Linked Leaf Nodes Optimize Range Queries
A sequential range query asks for all records with keys in an interval \([K_{\text{start}}, K_{\text{end}}]\). In a B-tree without linked leaves, finding the next key after \(K_{\text{start}}\) often requires traversing back up to parent nodes and descending into sibling subtrees, causing random I/O and repeated node visits.
In a B+ tree, every data record resides at the leaf level, and each leaf node contains a pointer to the next leaf node in sorted key order. Executing a range query follows a simple two-step process:
- Point Lookup: Traverse from the root to the leaf node containing \(K_{\text{start}}\) in \(O(\log_m N)\) page reads.
- Sequential Scan: Read records from the starting leaf and follow the leaf-to-leaf pointers until a key greater than \(K_{\text{end}}\) is reached.
If the range contains \(R\) matching records and each leaf node holds \(L\) records, the sequential scan requires only \(\lceil R / L \rceil\) additional page reads.
Hardware and Storage Alignment in Classical Computing
Classical computing architectures—whether using spinning hard drives (HDDs), solid-state drives (SSDs), or CPU caches—strongly favor sequential memory access over random access.
- Disk and SSDs: Reading contiguous or sequentially linked pages allows storage controllers and operating systems to perform read-ahead prefetching, amortizing seek and latency costs across many records.
- CPU Cache Efficiency: Because internal nodes contain only keys and pointers, more of the upper tree levels fit into RAM or CPU caches, keeping root-to-leaf traversals fast while leaf scans stream data predictable into memory.
By combining high-fanout internal nodes with a doubly or singly linked list at the leaf level, B+ trees remain the standard indexing structure for relational databases and file systems that rely on fast range scans.