Managing Indexes
1. Reindexing Table
REINDEX TABLE orders;
REINDEX TABLE CONCURRENTLY orders;
2. Reindexing Index
REINDEX INDEX orders_cust_idx;
REINDEX INDEX CONCURRENTLY orders_cust_idx;
3. Reindexing Schema
REINDEX SCHEMA public;
4. Reindexing Database
REINDEX DATABASE shop; -- requires being connected to shop
REINDEX SYSTEM shop; -- system catalogs only (single-user)
5. Reindexing Concurrently
| Form | Lock |
|---|---|
| REINDEX (default) | ACCESS EXCLUSIVE |
| REINDEX CONCURRENTLY | ShareUpdateExclusive |
6. Checking Index Usage
SELECT relname, indexrelname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC LIMIT 20;
7. Finding Unused Indexes
SELECT s.schemaname, s.relname, s.indexrelname,
pg_size_pretty(pg_relation_size(s.indexrelid)) AS size,
s.idx_scan
FROM pg_stat_user_indexes s
JOIN pg_index i ON i.indexrelid = s.indexrelid
WHERE s.idx_scan = 0 AND NOT i.indisunique AND NOT i.indisprimary
ORDER BY pg_relation_size(s.indexrelid) DESC;
8. Finding Duplicate Indexes
SELECT array_agg(indexname) AS dups, array_agg(indexdef)
FROM pg_indexes
GROUP BY tablename, regexp_replace(indexdef, ' INDEX [^ ]+', '')
HAVING count(*) > 1;
9. Analyzing Index Bloat
CREATE EXTENSION IF NOT EXISTS pgstattuple;
SELECT * FROM pgstatindex('orders_cust_idx');
-- or use pg_stat_user_indexes + pg_class for size deltas
10. Optimizing Index Maintenance
| Practice | Detail |
|---|---|
| Use CONCURRENTLY | Avoid downtime on rebuilds |
| Schedule REINDEX | After major delete/update cycles |
| Increase maintenance_work_mem | Speeds creation/rebuild |
| Monitor bloat | pg_stat_user_indexes + pgstattuple |
| Drop unused | Frees write overhead |