CMD Guide
HomeSystem DesignSystem Design Building Blocks

Indexes

An index is a second copy of one or more columns kept in a sorted, high-fanout balanced tree (almost always a B+tree) that sits beside the table; because the keys are sorted, the database finds a row by making a handful of comparisons that halve the search space each step — roughly log(n) node visits — instead of reading every row. That single structural fact is the whole story: reads get cheap because the data is ordered, and writes get more expensive because that order must be maintained on every insert, update, and delete.

Why a sorted structure wins: the numbers

Take a books table with 1,000,000 rows and a query WHERE id = 42. Without an index the engine does a full table scan: it reads rows one by one until it finds 42 (or reaches the end to prove there is no more). That is O(n) — on average 500,000 row reads, worst case 1,000,000.

A B+tree index on id stores those keys sorted and packed into fat nodes. A realistic node (one disk page, ~8 KB) holds on the order of 100+ keys, so the tree fans out by ~100 at every level. That means:

So a million-row table needs a tree only 3 levels deep. A lookup touches 3 nodes — root, internal, leaf — then one pointer to the row. That is O(log n), and because the fanout is ~100 (not 2), the base of the log is huge and the height barely grows: a billion rows is still only ~5 levels. The comparison, per point lookup:

StrategyNode/row readsGrowth
Full scan~500,000O(n)
B+tree index~3 + 1 row fetchO(log n)

Tracing one lookup

Suppose the B+tree on id looks like the diagram below and we run SELECT * FROM books WHERE id = 42. The traversal:

  1. Root holds separator keys [30 | 60]. Compare 42: since 30 ≤ 42 < 60, follow the middle pointer.
  2. Leaf node [30, 42, 55]: binary-search within the node, land on 42.
  3. The leaf entry for 42 carries a row pointer (a primary-key value or a physical page/row id). Follow it once to read the full row.

Three comparisons plus one fetch instead of scanning ~500,000 rows. And because leaves are chained left-to-right, a range query like WHERE id BETWEEN 42 AND 90 finds 42 the same way, then walks the leaf chain — no re-descending the tree per row. That leaf ordering is exactly why a B+tree also accelerates ORDER BY, >/<, and prefix matches, not just equality.

diagram
diagram

Composite indexes and the leftmost-prefix rule

An index on multiple columns, e.g. INDEX (last_name, first_name), sorts by last_name first, then first_name within each last name — like a phone book. This means the index only helps a query if it uses a leftmost prefix of the key columns:

A related lever is the covering index: if the index already contains every column the query returns, the engine answers from the index alone (an index-only scan) and skips the second hop to the table row entirely. INDEX (last_name, first_name) covers SELECT first_name WHERE last_name = 'Kumar' — no row fetch needed. A complementary lever is the partial index (Postgres) / filtered index (SQL Server): index only the rows matching a predicate — e.g. CREATE INDEX ... WHERE status = 'ACTIVE' — so a small hot subset of a huge table gets a tiny, cheap-to-maintain index instead of one spanning every dead row.

Pitfalls

When to use it — and when not

Reach for a B+tree index when a column is queried selectively and often, especially for equality and range/ordering/prefix work (WHERE, JOIN keys, ORDER BY, BETWEEN). It is the default for a reason: it serves point lookups, ranges, sorting, and prefix scans from one structure. The cost you accept is extra storage and slower writes.

Signals you should NOT add one: the table is tiny (a scan is already cheap and the tree is pure overhead); the query returns a large fraction of rows (a scan beats millions of random pointer hops); or the workload is write-dominated and rarely read (you'd be taxing the common operation to speed up the rare one).

Trade-offs versus named alternatives:

Takeaways


Re-authored and deepened for this guide. Sources: Ramakrishnan & Gehrke, Database Management Systems (B+tree structure and cost model); Kleppmann, Designing Data-Intensive Applications, ch. 3 (B-trees vs LSM-trees, write vs read amplification); the PostgreSQL and MySQL InnoDB documentation on index types, composite/leftmost-prefix rules, and covering (index-only) scans; and Wikipedia: Database index.

🤖 Don't fully get this? Learn it with Claude

Stuck on Indexes? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🎨 Explain it visually

Build the mental picture, not memorization.

I just read a lesson on **Indexes** (System Design) and want to truly understand it. Explain Indexes from first principles using ONE vivid real-world analogy and a visual mental model — draw it as ASCII art or a clear step-by-step diagram — with a concrete example using real numbers. Then ask me one question to check I got the mental picture, and wait for my reply. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🤔 Walk me through it (interactive)

Socratic — adapts to where you're stuck.

Teach me **Indexes** interactively. Ask me ONE guiding question at a time, wait for my answer, and adapt to my confusion — build the idea with me step by step instead of explaining it all at once. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧪 Quiz me & fix my gaps

Active recall exposes what you missed.

Quiz me on **Indexes** with 5 questions, easy to tricky, ONE at a time. Tell me if each answer is right; at the end, explain clearly what I got wrong and why. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🧠 Make it stick

Intuition + hook + flashcards for long-term memory.

Help me remember **Indexes** for the long term: give the one-sentence intuition, a memorable hook/mnemonic, a tiny worked example, and 3 active-recall flashcards (Q -> A). If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes