서비스가 느려질 때 범인은 대부분 DB 쿼리입니다.
PostgreSQL의 쿼리 성능을 개선하는 핵심 기법을 정리합니다.
가장 먼저 EXPLAIN ANALYZE
EXPLAIN ANALYZE
SELECT * FROM orders WHERE user_id = 1234 AND status = 'pending';
이 명령으로 쿼리의 실행 계획과 실제 소요 시간을 확인합니다.
Seq Scan이 보이면 풀 테이블 스캔 중이라는 뜻이고, 인덱스가 없다는 신호입니다.
인덱스 전략
단순 인덱스:
CREATE INDEX idx_orders_user_id ON orders(user_id);
복합 인덱스 (자주 함께 사용하는 컬럼):
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
복합 인덱스는 선행 컬럼부터 적용됩니다.
WHERE status = 'pending' 단독 조건에는 위 인덱스가 사용되지 않습니다.
부분 인덱스 (특정 조건에 해당하는 행만):
CREATE INDEX idx_pending_orders ON orders(user_id)
WHERE status = 'pending';
처리 중인 주문만 자주 조회한다면, 이 방식이 훨씬 효율적입니다.
N+1 쿼리 문제
ORM(SQLAlchemy, TypeORM 등)을 쓸 때 가장 흔한 성능 문제입니다.
리스트 조회 후 각 항목의 관계 데이터를 별도로 N번 조회하는 패턴입니다.
해결: JOIN 또는 eager loading을 사용하세요.
VACUUM과 통계 업데이트
PostgreSQL의 MVCC 特性상 삭제/업데이트된 행이 물리적으로 남아 테이블이 bloat됩니다.
VACUUM ANALYZE orders;를 주기적으로 실행하거나 autovacuum 설정을 확인하세요.
쿼리 결과 캐싱
Redis를 활용해 자주 조회되는, 변경이 드문 쿼리 결과를 캐싱하면 DB 부하를 극적으로 줄일 수 있습니다.
성능 최적화는 측정 → 병목 확인 → 개선 → 재측정 사이클을 반복하는 과정입니다.
작성한 정보가 조금이나마 유익하고 도움이 되셨다면, 가시기 전에 아래 광고 한번 살짝 눌러주시면 정말 큰 힘이 됩니다. 감사합니다!