9. Indexes
1
The picture to keep in your head2
9.1 What is an index, exactly?3
9.2 What's the difference between a full table scan and an index lookup?4
9.3 What does an index look like inside?5
9.4 How do composite indexes work, and what is the leftmost-prefix rule?6
9.5 What is a covering index?7
9.6 How do you know whether a query uses an index?8
9.7 What does an index cost you?9
9.8 When does an index not help, or even hurt?10
Memory card and where the analogy breaks11
Practice: five levels12
Interview questions13
Solutions14
Sources15
Code lab9. Indexes
Practice: five levels
3 min read+10 XP
Assignments
Five levels. Do them in order. Answers are in "Solutions" at the end, so try first.
Level 1: Think (no code)
A. Will an index help? Say which index, or why not.
SELECT * FROM users WHERE email = ?on 5 million users.SELECT * FROM orders WHERE status = 'paid', where 80% of orders are paid.SELECT * FROM books WHERE title LIKE '%design%'.SELECT * FROM orders WHERE user_id = ? ORDER BY created_at DESC LIMIT 20.SELECT * FROM countries WHERE code = 'IN'on a table of 250 countries.
B. You have an index on (user_id, created_at). Which of these can seek using it?
WHERE user_id = 7WHERE created_at > '2026-01-01'WHERE user_id = 7 AND created_at > '2026-01-01'WHERE created_at > '2026-01-01' AND user_id = 7(same as 3, columns written in a different order)
Level 2: Calculate
- A B-tree page holds about 500 keys. How many levels does an index need for 10 million keys? For 1 billion?
- An orders table has 10 million rows of about 100 bytes. Roughly how long does a full scan take from disk at 500 MB a second? An index lookup reads about 4 pages at about 0.1 ms each. How long does that take?
- The orders table has the primary key plus 5 other indexes. During a sale it takes 1,000 inserts a second. How many index entries are written each second, including the table itself?
statushas 3 values spread evenly across 200,000 orders. About how many rows doesWHERE status = 'paid'match? Why might the planner ignore an index onstatus?
Level 3: Build
Using Python's sqlite3:
- Create an
orderstable with 200,000 rows (user_id, created_at, status, total) and auserstable with emails. - Write
plan(db, sql)that returns the output ofEXPLAIN QUERY PLAN, andtimed(db, sql)that measures a query. - Show, with assertions on the plan text, that:
WHERE user_id = ?is aSCANwithout an index and aSEARCH ... USING INDEXwith one, and gets much faster;- a
(user_id, created_at)index is used foruser_idand foruser_id + created_at, but can't seek oncreated_atalone; SELECT created_at ... WHERE user_id = ?uses a covering index.
- Also write a sorted-list "index" with binary search and count comparisons vs a scan over 1 million keys.
- Measure 20,000 inserts with 0 and with 5 indexes.
Level 4: Debug
Login is slow, and it gets slower as the site grows. There is an index on users(email).
python
- Find the bug. Why isn't the index used? What does
EXPLAIN QUERY PLANshow? - Fix it. Give two fixes.
Level 5: Design
The bookstore's orders table has 50 million rows. These queries run constantly:
- A: "My orders":
WHERE user_id = ? ORDER BY created_at DESC LIMIT 20 - B: Admin search:
WHERE status = ? AND created_at BETWEEN ? AND ? - C: Order page:
WHERE id = ? - D: Nightly report: total sales per day for the last year
Deliver:
- The indexes you'd create (columns and order), and which query each serves.
- Which query you would not add an index for, and why.
- How you'd check the indexes are actually used.
- How you'd add the new indexes to the live table without hurting the site.
- The write-cost impact during a sale, and what you'd watch.