본문으로 건너뛰기

7.2 Lock, bloat, maintenance

SQL이 느린 이유가 plan은 아닐 수 있습니다. Lock 대기, 오래된 transaction, dead tuple, checkpoint와 autovacuum 경합을 먼저 분리합니다.

SELECT pid, state, wait_event_type, wait_event,
now() - query_start AS query_age,
pg_blocking_pids(pid) AS blockers,
left(query, 100) AS query
FROM pg_stat_activity
WHERE state <> 'idle'
ORDER BY query_start;
SELECT relname, n_live_tup, n_dead_tup,
last_autovacuum, autovacuum_count
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;

EXPLAIN ANALYZE를 isolated session에서 실행하면 production lock contention이 재현되지 않을 수 있습니다. Wait event와 blocker chain, transaction age를 incident 시점에 보존합니다.

Table과 index bloat는 정확한 단일 catalog column이 아닙니다. Statistics 기반 추정, pgstattuple, physical size, workload를 조합하고 extension의 lock과 I/O 영향도를 검토합니다.

Vacuum과 REINDEX CONCURRENTLY도 I/O, WAL, disk space, lock을 사용합니다. Query 튜닝과 maintenance를 같은 change window에 섞지 않고 각각 효과를 측정합니다.