Overview
A secondary index maps values of non-primary-key columns to row locations so the planner can satisfy WHERE, JOIN, and ORDER BY without scanning the table. Every index speeds some reads and slows each INSERT, UPDATE, and DELETE that touches its columns, so add one only for a query you have measured.
Rules
- Pick the type by operator: btree-index (default: equality, range, sort), gin-index (arrays, full-text, JSONB), GiST (geometry, nearest-neighbor), BRIN (huge, naturally ordered tables), Hash (equality only).
- Confirm use with
EXPLAIN (ANALYZE, BUFFERS). Drop indexes whosepg_stat_user_indexes.idx_scanstays at zero across a full business cycle. - Index foreign-key columns on the child table; PostgreSQL does not do it for you (foreign-key).
- Partial (
WHERE active) and expression (lower(email)) indexes cover narrow access patterns at smaller size. Updates that change no indexed column can be HOT updates that skip index maintenance (write-amplification).
CREATE INDEX users_email_active_idx ON users (email) WHERE active = true;Related
- btree-index: the default index type.
- gin-index: index for composite values.
- foreign-key: FK columns need an index.
- write-amplification: the write cost of each index.
- postgres-indexes: index strategy.
- postgres-explain: verify index use.