The Runtime Theory
easyApplicationDSA#indexes#storage#b-trees

Why are B-trees used for indexes instead of binary search trees?

The interviewer is testing whether you know indexes live on disk and that I/O, not comparisons, is the cost model — fanout, page-size nodes, and why BST pointer-chasing fails.

The Runtime Theory Team2 min readasked at google · amazon · microsoft

The question separates people who think in RAM from people who think in disk. A binary search tree is a beautiful data structure in memory: O(log n) lookups, trivial to reason about. But a database index doesn't live in RAM — it lives on disk, and the entire design changes when the bottleneck is I/O, not comparisons.

The cost model is the whole answer. On disk, each node you visit is a random read: the disk head seeks, the page transfers, milliseconds pass. A BST of 1 billion keys has ~30 levels, so a lookup is ~30 random disk reads — 30 seeks, and a couple hundred milliseconds of latency. A B-tree of the same data is three or four levels.

The trick is fanout. A B-tree node is not a key and two child pointers; it's a full database page, typically 4-16KB. Each node holds hundreds of keys (InnoDB: ~300+ per 16KB page; Postgres: ~270 per 8KB page), and each node has one child pointer per key plus one more. With a fanout of ~1000, a billion rows sit in a tree of height 3-4. One lookup = one root read (almost always cached in the buffer pool), one or two child reads, and the leaf — two or three disk I/Os total. That's the entire argument, and it's quantitative: B-trees reduce I/O by 10x because each I/O delivers a page full of keys instead of one key.

The mechanics matter too. A B-tree node is exactly one page, so a split or merge is one page write. Leaves are linked left-to-right, which is what makes range scans (WHERE id BETWEEN ...) a sequential scan of the leaf chain rather than repeated root-to-leaf treks. The tree stays balanced by construction — insertion splits overflowing nodes, deletion merges underfull ones — so no worst-case degeneracy like a BST fed sorted keys, which becomes a linked list.

The honest edge cases: the buffer pool caches the top levels, so real systems rarely touch disk for the root; that's why your index lookup in a hot cache costs microseconds, not milliseconds. Write-heavy workloads where random page writes dominate are why LSM trees exist — they trade O(log n) point reads and read amplification for sequential write batching. And the choice matters because this isn't a theoretical micro-optimization: it's the difference between a lookup that costs one disk seek and one that costs thirty.

This answer walks

Follow-ups they'll push on

  1. 01Why does the B-tree node size match the database page size?
  2. 02What happens to the B-tree when keys are inserted in sorted order?
  3. 03When would you prefer an LSM tree over a B-tree?

More interviews in this topic

One dispatch a week

The trace behind each question, the tradeoff that explains it, and one technical dispatch per week — no noise.

One technical dispatch per week. No noise.