intermediate
Index types
Choose B-tree, GIN, GiST, BRIN, partial, expression, and composite indexes by access path.
PostgreSQL offers more index families than a default B-tree. Pick the type that matches the predicate, not the column name.
| Index type | Typical use | |------------|-------------| | B-tree (default) | Equality, range, ORDER BY on scalars | | GIN | JSONB containment, arrays, full-text | | GiST | Geometry, ranges, nearest-neighbor | | BRIN | Very large, naturally ordered tables (time series) | | Hash | Legacy equality-only; rarely beats B-tree today |
Partial indexes shrink write cost when queries always filter the same way:
CREATE INDEX idx_orders_open ON orders (created_at)
WHERE status = 'open';
CREATE INDEX idx_users_email_lower ON users (lower(email));
Composite index column order must follow equality filters first, then range/sort columns. Expression indexes help when the query applies a function to the column.
On interviews: name the access path (equality vs range vs containment), explain why GIN fits JSONB/@> but not every column, and mention index maintenance on writes.
Common pitfalls: indexing every column; using GIN on low-cardinality booleans; wrong composite column order; forgetting partial indexes for hot subsets.
The trade-off is read speed versus write amplification, storage, and planner surprises — fewer, targeted indexes usually beat a blanket index strategy.
Checklist:
- Match index family to predicate shape.
- Use partial indexes for stable filter subsets.
- Order composite keys by equality then range.
- Verify with EXPLAIN (ANALYZE, BUFFERS).