BOOK DEEP READ · DATABASE INTERNALS · CH 2

B-Tree Basics

Database Internals · Ch 2 · Alex Petrov · 2019

中文 →

What is this chapter about?

You look up a three-year-old order by its number, and out of billions of records it comes back in a fraction of a second. The database does that with an index — a table of contents that can pin down any entry instantly. This chapter is about the one way of building that table of contents that almost everybody uses: the B-Tree. It was invented in 1972, and fifty years later it is still the default index in MySQL, PostgreSQL, SQLite and Oracle. Why that one?

Start with something odd

The search tree you were taught in class asks a yes/no question at every step: bigger or smaller? left or right? In memory that works beautifully. Move the very same tree onto a disk and it becomes unusably slow. The arithmetic of "fast" suddenly comes out wrong.

Why the old world struggled

Here is the catch: a disk does not sell you one byte. Even if you want a single byte, it hauls back a whole block — thousands of bytes at a minimum. The trip is expensive; how much you carry back barely matters.

And a tree that forks two ways has exactly one signpost at each fork. With billions of records you have to ask "left or right?" thirty-odd times in a row, and every question means another trip to the disk. The slowness lives in the number of trips, not the number of comparisons.

The core idea: turn a signpost into a directory page

Trick one: stop putting a single signpost at each fork. If the disk insists on hauling a whole block anyway, pack that block full of signposts — one sheet listing hundreds of ranges: "orders 10,000–50,000 on that shelf, 50,000–90,000 on the next one." One glance tells you where to go next, the way you find a word by the letter tabs on the side of a dictionary rather than turning pages. The result is a tree squashed flat: thirty-odd levels become three or four. And the top two or three levels are small enough to live in memory permanently, so a lookup usually costs just one real trip to the disk.

Trick two is prettier: this tree grows from the bottom up. New data goes into the bottom page; when that page fills, it splits in two and hands its middle signpost up to the level above; if that level fills, it hands one up too; and only when the very top page can no longer cope does the whole tree gain a level, all at once. Because growth always happens at the top, every leaf sits exactly the same distance from the root — the tree is level by construction and never needs the endless rebalancing other trees do.

Trick three is for flipping pages: the real data lives only on the bottom row, and those bottom pages are joined hand to hand in a chain. So "list the thousand orders after March 1st" means finding the starting point and walking the chain — never climbing back to the top.

What it buys you

Fifty years of dominance come from doing three things at once: finding one record fast, finding a whole run of them fast, and still allowing inserts and deletes while staying in order. A hash table finds one record fast too, but it has no notion of order, so the other two are out of reach.

The honest cost, in one sentence: it prefers data that arrives in order — counters and timestamps keep it happy; a primary key made of random codes gets pages sliced up until they sit half empty, wasting space and making writes more expensive.

Remember this

A B-Tree is not a cleverer search tree — it is a search tree rebuilt around the disk's temperament. Since the disk can only haul whole blocks, fill a whole block with signposts and fork hundreds of ways at once, and thirty levels collapse into three or four. What you save is not comparisons; it is trips to the disk.

Want the mechanisms, the notation and the diagrams? → Switch to the deep read