DBAtlas · 데이터베이스 운영 아틀라스

pg_stat_io로 I/O 발생원 분석(backend 유형, 객체, context)

PostgreSQL익스텐션

명령어

SELECT backend_type,
       object,
       context,
       reads,
       pg_size_pretty(reads * op_bytes) AS read_size,
       writes,
       pg_size_pretty(writes * op_bytes) AS write_size,
       extends,
       hits,
       round(100.0 * hits / NULLIF(hits + reads, 0), 1) AS hit_pct,
       evictions,
       reuses,
       fsyncs,
       round(read_time::numeric, 1) AS read_ms,
       round(write_time::numeric, 1) AS write_ms
FROM pg_stat_io
WHERE coalesce(reads, 0) + coalesce(writes, 0) + coalesce(extends, 0) + coalesce(evictions, 0) > 0
ORDER BY coalesce(reads, 0) + coalesce(writes, 0) DESC;

-- Who writes? Ideally most writes come from the checkpointer and background writer
SELECT backend_type,
       pg_size_pretty(sum(writes * op_bytes)) AS written,
       round(100.0 * sum(writes) / NULLIF(sum(sum(writes)) OVER (), 0), 1) AS pct_of_writes,
       sum(fsyncs) AS fsyncs
FROM pg_stat_io
WHERE object = 'relation' AND writes > 0
GROUP BY backend_type
ORDER BY sum(writes) DESC;

하는 일

backend 유형(client backend, autovacuum, checkpointer...), 객체(relation/temp relation), context(normal, vacuum, bulkread, bulkwrite)별 읽기, 쓰기, extend, eviction, fsync와 쓰기가 어떤 프로세스 유형에서 오는지 보여 준다.

사용 시점

I/O 병목 시 부하가 쿼리, autovacuum, checkpoint 중 어디서 오는지 판별하고 shared_buffers/bgwriter 설정을 검증하기 위해.

주의

pg_stat_io는 클러스터 전체 범위이며 마지막 reset 이후 누적이다. 변화를 보려면 두 샘플의 차이를 구한다(reset: SELECT pg_stat_reset_shared('io');). read_time/write_time은 track_io_timing = on일 때만 채워진다. reads에는 OS page cache에서 처리된 읽기도 포함된다. client backend의 쓰기나 eviction이 높으면 backend가 공간 확보를 위해 buffer를 직접 쓰는 것이므로 shared_buffers, bgwriter_lru_maxpages, checkpoint 설정을 검토한다. context = 'vacuum'/'bulkread' 행은 ring buffer 사용을 반영하며 그곳의 reuse는 정상이다.

DBAtlas에서 열기 →

관련 항목