운영 중인 서비스에서 데이터 센터로부터 CPU 사용량이 MAX를 기록했다는 알림 메일을 받았다. 처음에는 특정 시간대에만 발생하는 문제라면 크론잡(cron job) 관련 이슈일 가능성을 생각했지만, 실제로는 불특정 시간에 지속적으로 발생하는 문제였다.
CPU 사용률이 급증하는 원인을 파악하기 위해 데이터베이스 성능부터 점검해보기로 했다. PostgreSQL에서 테이블별 스캔 통계를 확인할 수 있는 쿼리를 실행했다.
SELECT schemaname, relname, seq_scan, seq_tup_read, idx_scan
FROM pg_stat_user_tables
ORDER BY seq_tup_read DESC;
이 쿼리를 통해 각 테이블의 아래 목록을 확인할 수 있었다:
통계 결과를 분석한 결과, 가장 많이 스캔되는 상위 4개 테이블에서 인덱스가 설정되지 않은 컬럼들이 빈번하게 조회되고 있었다. 이로 인해 매번 전체 테이블을 스캔(Full Table Scan)하면서 CPU 사용률이 급증한 것으로 판단되었다.
운영 중인 서비스이므로 서비스 중단 없이 인덱스를 추가해야 했다. PostgreSQL의 CONCURRENTLY 옵션을 사용하여 인덱스를 생성했다.
CREATE INDEX CONCURRENTLY index_name ON "table_name" ("column_name");
인덱스 추가 후 쿼리 실행 시간을 테스트해보았다.
EXPLAIN (ANALYZE, BUFFERS)
SELECT "table"."column"
FROM "table"
WHERE "table"."column" = 'test_value'
LIMIT 1;
실행 계획 분석 결과, 쿼리 실행 시간이 대폭 단축되었다.
간단한 인덱스 추가만으로도 시스템 성능을 크게 개선할 수 있었던 사례였다.
자세한건 운영팀의 모니터링 결과를 좀 보긴 해야한다..!