데이터베이스가 재시작되면 버퍼에 유지되고 있던 데이터들은 모두 제거되며 shared buffer에 다시 채워지기 전까지 해당 데이터에 접근하면 쿼리 성능이 떨어진다.
이때 pg_prewarm을 사용하면 수동 캐싱을 하거나 환경설정을 통해 자동 캐싱을 할 수 있다.
- 수동 캐싱 평소에 자주 사용하는 대량의 테이블의 데이터를 캐싱하지 않아서 디스크 엑세스로 인해 성능저하가 예상이 된다면 수동 기능을 통해서 캐싱을 시킬수 있다.
결과
실행 결과 의미 1회차 read=4480shared_buffers에 아무것도 없음. 실제 디스크에서 읽음 2회차 hit=33 / read=4447반복해도 캐시가 안 채워짐 (링 버퍼 전략). OS 페이지 캐시에서 읽었을 것 3회차 (prewarm 후) hit=4480100% shared_buffers 적중 핵심 3가지
read≠ 디스크 I/O — “shared_buffers에 없었다”는 뜻일 뿐. 뒤에 OS 페이지 캐시가 있어서 실제 디스크까지 안 갔을 수 있음. 구분하려면track_io_timing = on.큰 테이블 Seq Scan은 반복해도 캐시가 안 쌓인다 — 테이블이
shared_buffers / 4보다 크면 256KB 링 버퍼만 재사용. 버그가 아니라 다른 쿼리의 캐시를 보호하려는 의도된 동작. 단, 이미 캐시에 있는 블록은 정상적으로 hit 되므로 prewarm 효과는 유지됨.해법 — 즉시 채우려면
pg_prewarm, 계속 유지하려면shared_buffers를 테이블 크기의 4배 이상으로. 재시작 후 자동 복원은 autoprewarm.캐싱 명령
create extension pg_prewarm; select pg_prewarm('public.tb_warm');두 번째 인자를 생략하면 기본값이
'buffer'라서pg_prewarm('public.tb_warm', 'buffer')와 동일하게 shared_buffers까지 적재됩니다.확인 명령
SELECT count(*) FROM pg_buffercache WHERE relfilenode = pg_relation_filenode('tb_warm');
- 자동 캐싱 pg_prewarm.autoprewarm 기능을 사용하면 shared buffer 영역에 있는 페이지들을 자동으로 미리 워밍업할 수 있다. 그로 인해 디스크IO에 대한 비용을 절감시킬 수 있다. 해당 기능을 적용하면 재시작이 필요하다.
postgresql.conf 파일 설정
shared_preload_libraries = 'pg_prewarm' -- 서버가 시작될때 로드해야되는 라이브러리 설정
pg_prewarm.autoprewarm = true -- 작업자 실행 여부,기본값 true, 변경시 재시작 필요
pg_prewarm.autoprewarm_interval = 300s -- 파일변경에 대한 시간간격 설정
위의 설정을 하면 autoprewarm master 백그라운드 프로세스가 생성되어 autoprewarm_interval 설정값에 따라 shared-buffer 영역에 있는 데이터들을 autoprewarm.blocks 파일에 저장한다.
정상 종료시에도 저장하며 실제 데이터는 저장하지 않아서 파일이 작다.
재시작 되면 설정대로 데이터 복원을 시작한다.
[Master] autoprewarm.blocks 읽기
↓
목록 정렬(정렬하는 이유는 순서대로 읽어야지 sequential I/O 적용됨)
↓
[Worker] shared_buffers로 블록 로드
↓
Worker 종료 → Master는 다시 주기적 저장 모드로