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

FormLock
REINDEX (default)ACCESS EXCLUSIVE
REINDEX CONCURRENTLYShareUpdateExclusive

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

PracticeDetail
Use CONCURRENTLYAvoid downtime on rebuilds
Schedule REINDEXAfter major delete/update cycles
Increase maintenance_work_memSpeeds creation/rebuild
Monitor bloatpg_stat_user_indexes + pgstattuple
Drop unusedFrees write overhead