Database Indexes: How They Work and What Types Exist
Fast recall
Quick revision
Core answer
Whether you understand the internal mechanics of indexes well enough to decide when to add them, when not to, and what the write penalty is.
Adding indexes on every column just in case. Each index slows down inserts and updates because the index structure must be maintained. Index bloat is a real operational problem.
Discuss covering indexes (index-only scans), composite index column ordering, and partial indexes for filtering a subset of rows.
Interview-ready guide
Interview answer
You've seen that indexes make queries faster — the more useful question is why some indexes are used and others are ignored, and why adding too many actually hurts performance.
B-tree — the default for almost everything
- A B-tree index keeps values in sorted order across balanced tree nodes, which means it handles equality (
=), ranges (BETWEEN,>,<), prefix matching (LIKE 'foo%'), andORDER BYall from one structure — O(log n) traversal instead of a full table scan - This is what PostgreSQL and MySQL InnoDB create when you run
CREATE INDEXwithout specifying a type
Composite indexes — column order is the critical decision
- An index on
(customer_id, status)sorts first bycustomer_id, then bystatuswithin each customer — which means it servesWHERE customer_id = ?orWHERE customer_id = ? AND status = ?, but notWHERE status = ?alone, because status has no starting sort position without customer_id - Put the most selective equality column first; range columns at the end
Covering indexes — zero heap fetches
- When the index contains every column a query needs, the database answers it entirely from the index without touching the table — called an index-only scan, which eliminates the most expensive I/O step for hot read queries
- Add non-key columns with
INCLUDE (col)in PostgreSQL to make any index covering without affecting the sort key
Partial indexes — index only the rows you actually query
- A partial index carries a WHERE clause —
CREATE INDEX ON orders(user_id) WHERE deleted_at IS NULL— which means it only indexes active rows, so it stays small and precisely aligned with the query pattern instead of growing with every soft-deleted record
Every index is a write tax — inserts and updates must maintain every index on the table. Run EXPLAIN ANALYZE before and after; never add an index without confirming it changes the plan.
Database Indexes: How They Work and What Types Exist
Direct Answer
A database index is a separate data structure that maps column values to row locations, allowing the database to find rows without scanning the entire table. The most common type is the B-Tree index, which supports equality and range queries. Other types include hash indexes (equality only), bitmap indexes (low-cardinality columns), and GiST/GIN indexes for full-text and JSON search.
Code Example
-- B-tree index: supports =, <, >, BETWEEN, LIKE 'prefix%'
CREATE INDEX idx_orders_customer ON orders(customer_id);
-- Composite index: column order matters
-- Good for WHERE customer_id = ? AND status = ?
-- Also usable for WHERE customer_id = ? alone (leading column)
-- NOT usable for WHERE status = ? alone
CREATE INDEX idx_orders_customer_status ON orders(customer_id, status);
-- Covering index: avoids heap fetch entirely
-- Query: SELECT status, total FROM orders WHERE customer_id = ?
CREATE INDEX idx_orders_covering ON orders(customer_id) INCLUDE (status, total);
-- Partial index: only indexes rows matching a condition
CREATE INDEX idx_active_orders ON orders(customer_id)
WHERE status = 'ACTIVE';
-- Hash index: equality-only, faster for = but no range support
CREATE INDEX idx_session_token ON sessions USING HASH (token);
-- GIN index: for full-text search and JSONB
CREATE INDEX idx_products_tags ON products USING GIN (tags);
// JPA: declare indexes on the @Table annotation
@Entity
@Table(name = "orders",
indexes = {
@Index(name = "idx_orders_customer_status",
columnList = "customer_id, status")
})
public class Order {
@Id private Long id;
private Long customerId;
private String status;
private BigDecimal total;
}
Common Mistakes & Pitfalls
Adding indexes on every column just in case. Each index slows down inserts and updates because the index structure must be maintained. Index bloat is a real operational problem.
Check your understanding
Answer these without looking back at the article.
- What is an index-only scan and when does it apply?
- How does a composite index differ from two separate single-column indexes?
- What happens to indexes during bulk inserts and how do you optimize that?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.