← Home
databasebackend

PostgreSQL Indexing Strategies


Why Indexes Matter

Without indexes, PostgreSQL must scan every row in a table to find matching records. For a table with millions of rows, this is painfully slow.

-- Without index: sequential scan (~500ms for 1M rows)
SELECT * FROM users WHERE email = 'tung@example.com';

-- With index: index scan (~1ms)
CREATE INDEX idx_users_email ON users(email);

B-tree Indexes (Default)

B-tree is the default and most common index type. It works well for equality and range queries:

CREATE INDEX idx_orders_created ON orders(created_at);

-- These queries benefit from the index:
SELECT * FROM orders WHERE created_at > '2024-01-01';
SELECT * FROM orders WHERE created_at BETWEEN '2024-01-01' AND '2024-06-30';

Composite Indexes

When you frequently query by multiple columns together:

CREATE INDEX idx_orders_user_status ON orders(user_id, status);

-- ✅ Uses the index (matches left-to-right)
SELECT * FROM orders WHERE user_id = 123;
SELECT * FROM orders WHERE user_id = 123 AND status = 'pending';

-- ❌ Cannot use the index
SELECT * FROM orders WHERE status = 'pending';

GIN Indexes

GIN (Generalized Inverted Index) is ideal for full-text search, JSONB, and array columns:

CREATE INDEX idx_posts_tags ON posts USING GIN(tags);

-- Fast array containment queries
SELECT * FROM posts WHERE tags @> ARRAY['go', 'backend'];

Partial Indexes

Index only a subset of rows to save space and improve performance:

CREATE INDEX idx_orders_pending ON orders(created_at)
WHERE status = 'pending';

This index is smaller and faster because it only includes pending orders.

EXPLAIN ANALYZE

Always verify your indexes are being used:

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

Look for Index Scan rather than Seq Scan in the output.

Summary

Index TypeBest For
B-treeEquality, ranges, sorting
GINJSONB, arrays, full-text search
PartialFrequently filtered subsets
CompositeMulti-column queries

Start with the queries you run most, then add indexes strategically. Too many indexes slow down writes.