PostgreSQL 인덱스 재작성과 재구성 비교
REINDEX의 목적과 잠금 특성, 무중단 재구성 대안, 모니터링 방법을 실무 관점에서 정리한 요약
목차
소개
인덱스는 조회 성능을 좌우한다. 하지만 시간이 지나면 인덱스가 비효율해지거나 손상될 수 있다. 본문은 REINDEX의 역할과 인덱스 재구성 대안을 비교하고, 운영 환경에서의 적용 절차와 검증 방법을 정리한다.
인덱스 문제 원인과 진단
인덱스가 나빠지는 이유
다음과 같은 상황에서 인덱스 효율이 떨어진다.
- 대량의 업데이트/삭제로 인한 빈 공간(bloat) 축적
- 잘못된 통계나 비효율적인 통계 샘플링
- 디스크 손상이나 파일 시스템 문제로 인덱스 손상
진단 방법
간단한 조회로 인덱스 크기와 사용량을 파악한다.
-- 인덱스 크기 상위 확인
SELECT schemaname, relname, indexrelname,
pg_size_pretty(pg_relation_size(indexrelid)) AS size
FROM pg_stat_all_indexes
WHERE schemaname = 'public'
ORDER BY pg_relation_size(indexrelid) DESC
LIMIT 20;
사용 빈도가 낮은 인덱스는 유지 비용이 크므로 재평가 대상이 된다.
REINDEX의 역할과 특성
무엇을 하는가
REINDEX는 기존 인덱스 파일을 재작성하여 내부 구조를 정리한다. 보통 손상 복구나 심한 bloat 해소에 사용된다.
잠금과 다운타임
REINDEX는 전통적으로 인덱스나 테이블에 대해 강한 잠금을 발생시킨다. 크기가 큰 객체에 대해 실행하면 쓰기 작업이 차단될 수 있다. 따라서 트래픽이 적은 시간대에 수행하는 것이 일반적이다.
실제 명령 예시
REINDEX 사용 예
-- 특정 인덱스 재작성
REINDEX INDEX idx_users_email;
-- 특정 테이블의 모든 인덱스 재작성
REINDEX TABLE public.users;
-- 데이터베이스 전체 인덱스 재작성
REINDEX DATABASE mydb;
이 명령들은 간단하지만 잠금 특성을 고려해야 한다.
무중단 재구성 전략
CREATE INDEX CONCURRENTLY 패턴
무중단으로 인덱스를 재구성하려면 기존 인덱스를 바로 대체하지 않고 새 인덱스를 동시 생성한 뒤 기존 인덱스를 제거하는 패턴을 사용한다. 이 방식은 쓰기 잠금을 거의 발생시키지 않는다.
-- 새 인덱스를 먼저 생성
CREATE INDEX CONCURRENTLY idx_users_email_new ON public.users (email);
-- 생성이 완료되면 기존 인덱스 제거
DROP INDEX CONCURRENTLY idx_users_email;
-- 필요하면 새 인덱스 이름 변경
ALTER INDEX idx_users_email_new RENAME TO idx_users_email;
외부 도구의 활용
pg_repack 같은 확장 도구는 테이블과 인덱스를 온라인으로 재구성하면서 디스크 사용량과 잠금을 최소화한다. 확장 설치와 테스트가 선행되어야 한다.
언제 REINDEX를 선택할까
- 인덱스 손상(corruption) 의심 시: REINDEX가 우선적 선택
- 심한 bloat가 존재하고 다운타임을 허용할 수 있을 때: REINDEX가 직접적 해결
- 무중단을 우선할 때: CREATE INDEX CONCURRENTLY 또는 pg_repack 사용
실무 체크리스트
- 대상 인덱스 크기와 사용량 확인
- 예상 소요 시간 산정(테스트 환경에서 시뮬레이션 권장)
- 백업 및 복구 계획 점검
- 성능 영향을 감시할 모니터링 지표 마련
모니터링과 검증
재작성 전후 비교
재작성 전후에 인덱스 크기와 쿼리 응답 시간을 비교한다. 다음 쿼리로 재작성 전후 차이를 확인할 수 있다.
-- 사용 빈도 낮은 인덱스 확인
SELECT indexrelname, idx_scan
FROM pg_stat_all_indexes
WHERE schemaname = 'public'
ORDER BY idx_scan ASC
LIMIT 20;
재작성 후 동일 쿼리와 응답 시간을 비교하면 효과를 판단할 수 있다.
결론
REINDEX는 손상 복구와 bloat 해소에 강력한 도구다. 반면 운영 중 서비스 가용성을 유지하려면 CREATE INDEX CONCURRENTLY 또는 pg_repack 같은 대안이 더 적합하다. 실제 운영에서는 모니터링 데이터를 기반으로 대상 선정과 수행 방법을 결정하면 안정성과 성능 모두를 확보할 수 있다.