[PostgreSQL] 스왑(swap)을 유발하는 무거운 쿼리 찾는 방법
PostgreSQL은 개별 쿼리 단위로 OS 스왑 메모리 사용량을 직접 추적하거나 기록하지 않습니다. PostgreSQL은 운영체제(OS)의 메모리 관리 영역인 스왑(Swap)을 직접 인지하지 못하며, 전체 프로세스 관점에서 메모리를 할당받아 사용하기 때문입니다.
하지만 임시 파일(Temporary Files)을 많이 생성하거나 과도한 메모리를 사용하는 쿼리를 역추적하여 스왑 유발 원인을 찾을 수 있습니다
스왑을 유발하는 무거운 쿼리 찾는 방법
pg_stat_statements활용- 확장 모듈인 pg_stat_statements를 사용해 정렬(Sort)이나 해시(Hash) 작업에서 디스크 임시 파일을 많이 생성하는 쿼리를 찾습니다.
temp_blks_read와temp_blks_written값이 큰 쿼리가 메모리(work_mem)를 초과해 디스크 I/O를 유발하고, 결국 OS 스왑으로 이어질 가능성이 높습니다. [1]
log_temp_files설정postgresql.conf에서log_temp_files = 0또는 특정 용량(예:10MB)으로 설정합니다.work_mem한도를 넘어 임시 파일을 만드는 쿼리의 텍스트와 사용량이 로그에 기록되므로 원인 쿼리를 특정할 수 있습니다. [1]
- OS 명령어와 프로세스 매핑
top,htop, 또는smem같은 OS 명령어로 현재 스왑을 가장 많이 쓰는 프로세스(PID)를 찾습니다.SELECT pid, query, state, age(clock_timestamp(), query_start) FROM pg_stat_activity WHERE pid = <PID>;쿼리를 실행해 해당 프로세스에서 실행 중인 쿼리를 직접 확인합니다.
임시 파일(디스크)을 가장 많이 생성하고 읽은 쿼리 상위 10개를 찾는 SQL 쿼리문
pg_stat_statements 뷰를 조회
SELECT
userid::regrole AS user_name,
dbid::regclass AS database_name,
-- 임시 블록 읽기/쓰기 합계 (블록 크기는 보통 8KB)
(temp_blks_read + temp_blks_written) * 8 / 1024 AS total_temp_mb,
temp_blks_read * 8 / 1024 AS temp_read_mb,
temp_blks_written * 8 / 1024 AS temp_write_mb,
calls AS execution_count,
-- 실행 1회당 평균 임시 파일 사용량
((temp_blks_read + temp_blks_written) * 8 / 1024) / NULLIF(calls, 0) AS avg_temp_mb_per_call,
total_exec_time / 1000 AS total_exec_time_seconds,
query
FROM
pg_stat_statements
WHERE
temp_blks_read > 0 OR temp_blks_written > 0
ORDER BY
total_temp_mb DESC
LIMIT 10;
쿼리 해석 팁
total_temp_mb: 이 값이 클수록work_mem이 부족해 디스크(임시 파일) 영역을 많이 썼다는 뜻입니다. OS 스왑을 간접적으로 유발하는 가장 유력한 후보들입니다.avg_temp_mb_per_call: 1번 실행될 때마다 평균적으로 얼마만큼의 임시 파일을 만들었는지 보여줍니다. 특정 쿼리가 소수만 실행되었어도 이 값이 매우 크다면 해당 쿼리의 정렬(Sort)이나 조인(Hash Join) 로직을 우선적으로 튜닝해야 합니다.
[연관 자료]




