Database Indexing
Make your queries 100x faster by telling the database where to look.
1The Library Analogy
2What is an Index?
Visual: How an Index Works
| row_id | name | |
|---|---|---|
| 1 | Charlie | c@mail.com |
| 2 | Alice | a@mail.com |
| 3 | Bob | b@mail.com |
| 4 | Diana | d@mail.com |
| name | → row_id |
|---|---|
| Alice | → 2 |
| Bob | → 3 |
| Charlie | → 1 |
| Diana | → 4 |
3Types of Indexes
B-Tree Index
Most common type. Balanced tree structure. Good for equality and range queries.
CREATE INDEX idx_user_name ON users(name);Hash Index
Uses hash function. Extremely fast for exact match, useless for ranges.
CREATE INDEX idx_session USING HASH ON sessions(session_id);Composite (Multi-column) Index
Index on multiple columns. Order matters! Left-to-right usage.
| last_name | first_name | → row |
|---|---|---|
| Adams | Alice | → 5 |
| Adams | Bob | → 2 |
| Baker | Carol | → 1 |
CREATE INDEX idx_name ON users(last_name, first_name);Full-Text Index
For text search. Tokenizes words, supports stemming and relevance scoring.
CREATE FULLTEXT INDEX idx_content ON articles(title, body);4Index Selection: What to Index
Good Candidates
Poor Candidates
5Index Usage: EXPLAIN
Use EXPLAIN to see if your query uses indexes:
EXPLAIN SELECT * FROM users WHERE email = 'alice@mail.com'; -- Good output (using index): Index Scan using idx_users_email on users Index Cond: (email = 'alice@mail.com'::text) -- Bad output (no index): Seq Scan on users Filter: (email = 'alice@mail.com'::text) Rows Removed by Filter: 999999
Indexes won't be used if you apply functions: WHERE LOWER(email) = 'alice' won't use index on email. Create a functional index instead: CREATE INDEX ON users(LOWER(email))
6The Cost of Indexes
Trade-off Visualization
7Covering Index (Index-Only Scan)
A covering index includes all columns needed by a query, avoiding the table lookup entirely:
-- Index on (email) SELECT name, email FROM users WHERE email = 'alice@mail.com'; 1. Look up email in index → get row_id 2. Go to table → fetch name
-- Index on (email, name) or INCLUDE SELECT name, email FROM users WHERE email = 'alice@mail.com'; 1. Look up email in index → name is there! No table access needed
CREATE INDEX idx_email_name ON users(email) INCLUDE (name);8Key Takeaways
9Interview Follow-up Questions
Interview Follow-up Questions
Common follow-up questions interviewers ask
10Test Your Understanding
Test Your Understanding
5 questions
What is the primary benefit of a database index?
You have an index on (city, created_at). Which query will use this index efficiently?
What is a major downside of having too many indexes?
What does EXPLAIN ANALYZE show that EXPLAIN doesn't?
When would a hash index be preferred over a B-tree index?