Advertisement

How Database Indexes Work — Why the Same Query Can Take 2ms or 8 Seconds

The phone book analogy that actually explains it, and how to find the problem with EXPLAIN

Muthu
18 July 20265 min read4 views

I once spent half a day chasing a "slow query" bug that turned out to be exactly this. 2 milliseconds versus 8 seconds. Same query, same table, same data. What separates those two numbers is almost never the query itself; it's whether the database had an index to jump to, or had to check every single row one by one to find what you asked for. Understanding that difference explains most of what "database performance" means in practice.

The Phone Book Analogy That Holds Up

Imagine looking up "Sharma" in a phone book that's sorted alphabetically — you flip to the S section directly, in seconds. Now imagine the same phone book with every entry in random order — you'd have to check every single page until you found it. An index is the alphabetical sorting. Without it, the database is doing the random-order search, checking every row, every time, no matter how simple the question.

What's Actually Happening Without an Index

Ask a database SELECT * FROM users WHERE email = 'x@example.com' on a table with no index on email, and it performs what's called a full table scan — it reads every single row in the table, checks if that row's email matches, and moves to the next one. On a table with 500 rows, you won't notice. On a table with 5 million rows, that's 5 million comparisons for one lookup, every single time that query runs.

What an Index Does

An index on a column builds a separate, pre-sorted structure (commonly a data structure called a B-tree) that maps values in that column directly to the rows that contain them. Instead of checking every row, the database jumps almost directly to the matching row, the same way you'd jump straight to the S section of the phone book. This is why adding one index can turn an 8-second query into an 8-millisecond one — you haven't changed the query or the data, you've changed how expensively the database has to search for it.

A Concrete Before-and-After

Without IndexWith Index
Rows checked to find one matchAll 5,000,000~23 (tree depth, roughly)
Time on a large tableSecondsMilliseconds
Cost to maintainNoneSlightly slower writes, more disk space

Why You Can't Just Index Every Column

This is the part beginners consistently get wrong: indexes aren't free. Every index has to be updated every time a row is inserted, updated, or deleted — so an over-indexed table gets meaningfully slower to write to, even though it gets faster to read from. The real skill isn't "add indexes," it's identifying which specific columns get searched or filtered on often enough to justify that ongoing write cost. A column you filter on constantly (like email, user_id, or status) is usually worth indexing. A column you rarely query directly usually isn't.

Where Indexes Matter

  • Columns used in WHERE clauses — the single most common reason to add an index
  • Columns used in JOIN conditions — joining two large tables without an index on the join column is one of the most common causes of a slow application
  • Columns used in ORDER BY — sorting a huge unindexed result set is expensive; an index in the right order can let the database skip the sort entirely
  • Foreign key columns — frequently joined against, and frequently forgotten when a table is first created

Where Indexes Don't Help (And Can Even Hurt)

  • Small tables — a full scan of 200 rows is already fast; an index adds write overhead for no meaningful read benefit
  • Columns with very few distinct values — indexing a boolean-like column (say, a status with only 3 possible values across 10 million rows) often doesn't help much, because the index still has to point to a huge chunk of matching rows
  • Columns rarely used in a WHERE, JOIN, or ORDER BY — an unused index is pure cost, no benefit

How to Actually Find the Problem in a Real Database

Most relational databases (Postgres, MySQL) let you ask directly what a query is doing with EXPLAIN in front of it:

EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'x@example.com';

If the output shows "Seq Scan" (sequential/full table scan) on a large table, that's the database telling you exactly what's slow and why — it's checking every row because nothing tells it where to jump directly. Adding CREATE INDEX idx_users_email ON users(email); and re-running the same EXPLAIN should show "Index Scan" instead, with a dramatically lower estimated cost.

Read the Query Plan Before You Guess

That half-day I mentioned earlier ended with one CREATE INDEX statement. A slow query is almost never mysteriously "heavy." It's the database doing more manual searching than it needs to, because nothing tells it where to look directly. Learn to read EXPLAIN output before reaching for any other fix, index the columns that get searched and joined on often, and resist the urge to index everything just in case, since that trade-off runs the other way on every single write, forever.

Frequently Asked Questions

No — every index slows down writes (inserts, updates, deletes) because it has to be maintained on every change. Index columns that are actually used often in WHERE, JOIN, or ORDER BY; leave the rest alone, especially on small tables or low-variation columns.

Advertisement

Affiliate Disclosure: This article contains affiliate links. If you purchase through these links, we may earn a commission at no extra cost to you.

Was this article helpful?

Advertisement

Share:

Comments

No comments yet. Be the first to share your thoughts!

Leave a comment

Advertisement

Related Posts

Advertisement