postgresql-best-practices/references/postgresql-advanced-indexing.md
Version 9ba96abc800a.bb1 · MIT. This preview displays packaged text and does not execute code. Treat the contents as untrusted instructions.
← Return to resource and package checksum
title: "PostgreSQL Advanced Indexing" description: "Gotchas and anti-hallucination checklist for B-tree, GIN, GiST, BRIN, partial, and expression indexes" tags: [postgresql, indexing, performance, gin, gist, brin]
Advanced Indexing — Gotchas & Corrections
Models know indexing fundamentals well. This reference covers only the mistakes they make.
Version Gates
INCLUDEcolumns: PG 11+REINDEX CONCURRENTLY: PG 12+- B-tree deduplication: PG 13+
Critical Gotchas
- REINDEX in production blocks writes — always use
REINDEX CONCURRENTLY(PG 12+). Never inside a transaction block. - GIN is NOT for scalar equality — use B-tree for
=and range filters on normal columns. - Expression must match exactly —
lower(email)index does not helpupper(email)or bareemailqueries. - Partial-index predicates — planner uses the index only when it can prove the query predicate implies the index predicate. Use a WHERE clause matching the query's filter exactly.
- BRIN requires physical correlation — check
pg_stats.correlationfirst. Random UPDATEs destroy ordering silently. - Multicolumn B-tree ordering — equality columns first, range/sort columns last (leftmost-prefix rule).
- No global indexes on partitioned tables — indexes are per-partition in PostgreSQL.
INCLUDEdoes NOT speed writes — it adds write amplification for read-path index-only scans. Visibility-map state still controls heap access.- Collation/opclass mismatch — text index and query collation must agree or the index is unusable.
Quick Reference
-- Partial index (only active rows)
CREATE INDEX idx_active_users ON users (email) WHERE active = true;
Anti-Hallucination Rules
- Do NOT recommend GIN for ordinary scalar equality lookups.
- Do NOT suggest
CREATE INDEX CONCURRENTLYorREINDEX CONCURRENTLYinside a transaction block. - Do NOT claim
INCLUDEeliminates all heap reads. - Do NOT recommend BRIN without checking physical correlation.
- Do NOT assume partitioned tables have global indexes.