advanced23 min studyLesson 271 in Engineering

B-tree pages: fanout is a layout calculation

Derive leaf capacity and internal fanout from a specified page format, then connect tree height to logical and physical access costs.

On this page

What you’ll understand

  • Distinguish leaf entries from internal routing separators.
  • Calculate capacity using page headers and complete entry widths.
  • Explain why tree height is neither a physical-read count nor an occupancy guarantee.

A B-tree index gains its shallow shape by routing through many children per internal page. That fanout comes from concrete bytes: separators, child references, headers, and layout overhead. Begin with a stated page format rather than a memorized logarithm. Then distinguish how many keys a perfectly packed tree could hold from how a changing database actually fills its pages.

Leaves store results; internal pages route searches

In the B+ tree style used for this lesson, leaf entries contain search keys and row references or payloads, while internal pages contain separators and child references. A search compares its key with separators and descends toward the appropriate leaf. The separator convention must define boundary equality and duplicates consistently. After locating a starting leaf, sibling links can support an ordered range scan without restarting at the root for every returned entry. Different B-tree variants place records differently, so state which layout is being analyzed.

An internal page with m children commonly needs m child references and m−1 separators in a simple teaching representation. A leaf does not have that same relationship: each leaf entry includes its own complete record reference or payload. Slot arrays, tuple headers, high keys, sibling pointers, and alignment also consume bytes. Our formulas collect fixed overhead in H and assume fixed-width entries. Variable-length keys, compression, deduplication, and truncated internal separators change actual capacity; an average width is an estimate rather than a hard limit.

Fmax⁡=⌊P−H+KD+K⌋,Lmax⁡=⌊P−HE⌋F_{\max}=\left\lfloor\frac{P-H+K}{D+K}\right\rfloor,\qquad L_{\max}=\left\lfloor\frac{P-H}{E}\right\rfloor
P and H are page and fixed-overhead bytes, K is separator bytes, D is child-reference bytes, and E is complete leaf-entry bytes. The fanout formula follows mD+(m−1)K≤P−H. Positive widths, P>H, and the stated fixed-width layout are assumed.↔ Scroll wide equations horizontally.

Full capacity and minimum occupancy are different claims

If every internal page has F children and every leaf contains L entries, a tree of h page levels can hold L times F to the power h−1 entries. This is a maximum-capacity model, not a promise that inserts always achieve those occupancies. For one count-based classical B+ policy, non-root internal pages have ceil(F/2) through F children and non-root leaves have ceil(L/2) through L entries; a non-leaf root has at least two children. Those bounds require compatible split and merge rules. Real database implementations can use different split targets, deferred deletion, or workload-specific fill policies. Do not transfer a textbook half-full invariant to every production page without checking its algorithm.

A useful estimate separates leaf fill from internal fanout. Wider included values can reduce leaf capacity without changing internal routing width in a design that excludes those values from upper levels. Skewed insertion patterns can leave some pages sparse and others frequently splitting. Keys also need a consistent total ordering under the chosen comparator or collation; violating that contract breaks navigation regardless of available space. Derive the shape from observed page statistics when capacity planning, and keep the maximum model as a sanity bound.

Nmax⁡(h)=LFh−1,h≥1,F≥2,L≥1N_{\max}(h)=L F^{h-1},\qquad h\geq1,\quad F\geq2,\quad L\geq1
N_max counts entries in a completely full B+ style tree with h root-to-leaf page levels, leaf capacity L, and internal fanout F including the root. It is an idealized upper capacity, excluding special metadata pages and implementation-specific root or separator formats.↔ Scroll wide equations horizontally.

Height describes navigation, not storage latency

A three-level search visits three logical index pages on its descent, but the root and upper internal pages may already be cached. A leaf miss can then dominate physical I/O. A range query adds leaf pages and may fetch table rows elsewhere, while an index-only scan has additional visibility requirements in MVCC systems. CPU comparisons, cache misses, latching, and decompression remain relevant even when every page is in memory. Avoid turning a tree-height calculation into an exact elapsed-time claim.

Use the cache lab to isolate reuse. Press Reset, set capacity C=4 and stride s=4, then predict that the sixteen initial requests over addresses 0,4,8,12 produce four misses and twelve hits. Play or Step to extend that same stream. For a separate experiment, Reset, set C=3 and s=4, predict zero hits for the repeating four-address cycle, then Play or Step. This is a fully associative LRU instrument, not a B-tree or buffer manager. It shows why a shallow tree's frequently reused pages and its physical-read cost require a workload argument.

Size a fictional three-level index

A teaching format uses 1,024-byte pages, 24 overhead bytes, eight-byte separators, eight-byte child references, and twenty-byte leaf entries. Estimate a maximally packed layout for 100,000 entries.

  1. The internal capacity is floor((1,024−24+8)/(8+8))=63 children. Leaf capacity is floor((1,024−24)/20)=50 entries.

  2. The leaves require ceil(100,000/50)=2,000 pages. Their parents require ceil(2,000/63)=32 pages, all of which fit under one root with capacity 63.

  3. The idealized layout has three page levels and 2,000+32+1=2,033 index pages, excluding metadata. Lower fill or wider actual entries can increase the count; caching determines which logical visits become physical reads.

The result

The simple format supports the proposed three-level layout. The calculation distinguishes routing fanout 63 from leaf capacity 50 rather than using one branching number for both.

Explore the model

Interactive lab

Interactive lab · cache

A working set can cross the capacity boundary

Reset, set C=4 and s=4, and predict 12 hits in the initial 16 requests. Play or Step. For a separate run, Reset, set C=3 and s=4, predict zero hits, then Play or Step. The deterministic LRU stream is a reuse illustration, not a B-tree or database-buffer simulation.

A working set can cross the capacity boundaryA fully associative LRU cache starts empty and requests address (i·s) mod 16. Hits move an address to the newest position; misses evict the oldest when full. Playback starts with 16 requests and adds two per second, capped at 4096 explicitly simulated requests. This toy stream is not a processor-cache benchmark. Current readings: Hits / requests: 0 / 16; Hit rate: 0%; Address-stream period: 16 addresses. All parameters are adjustable with the labeled controls below.Fully associative LRU cache after 16 deterministic requests: 0 hits and 16 misses.Most recent 16 requestsaddress = i × 3 mod 160M3M6M9M12M15M2M5M8M11M14M1M4M7M10M13MCurrent cache order · oldest → newest471013Latest address 13 · miss: inserted as newestToy address stream · period 16 · starts empty
Cached addressMiss / evictionMost recent request
Hits / requests
0 / 16
Hit rate
0%
Address-stream period
16 addresses
t = 0 s

A fully associative LRU cache starts empty and requests address (i·s) mod 16. Hits move an address to the newest position; misses evict the oldest when full. Playback starts with 16 requests and adds two per second, capped at 4096 explicitly simulated requests. This toy stream is not a processor-cache benchmark. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.

Look forLogical tree height and physical access cost differ when frequently reused pages remain cached.

Check your understanding

Why can widening leaf payload reduce leaf capacity without equally reducing internal fanout?

Try it yourself

Keep the example's page overhead and internal format, but widen complete leaf entries to forty bytes. Find leaf pages and page levels for 100,000 entries.

Take a moment to make a prediction or work it out on paper. Open a hint when you need one.

Give me a hint

Recalculate leaf capacity first, then divide the leaf count by fanout 63.

Compare with the solution

Leaf capacity becomes floor(1,000/40)=25, requiring 4,000 leaves. Their parents require ceil(4,000/63)=64 pages, which do not fit under a single 63-child root. One more internal level needs ceil(64/63)=2 pages under a root, giving four page levels in this packed model.

Take it with you

  • Leaf capacity and internal fanout follow different byte-layout constraints.
  • Maximum capacity does not establish actual fill or every variant's minimum occupancy.
  • Caching and table access separate tree height from physical latency.

Read further

Original sources and deeper explanations to follow at your own pace.

Optional progress, saved in this browser when available. Revisit any lesson at any time.

Lesson not marked complete.