PostgreSQL은 전통적으로 동기식 I/O 모델로 작동하여 각 읽기 요청이 시스템 호출을 차단했습니다. 이는 특히 네트워크 연결 스토리지(예: Amazon EBS)를 사용하는 클라우드 환경에서 1ms 이상의 지연을 유발하며 불필요한 대기 시간을 초래했습니다. 비동기 I/O는 여러 읽기 요청을 동시에 발행하여 이러한 병목 현상을 제거하고, 프로그램이 이전 읽기 완료를 기다리지 않고 계속 진행할 수 있도록 합니다.
PostgreSQL 18의 비동기 I/O 구현
-
PostgreSQL 17의 기반 마련: PostgreSQL 17에서 도입된 읽기 스트림 API는 읽기 작업 발행 방식을 표준화하고
posix_fadvise()를 통한 사전 데이터 페치를 간소화했습니다. 그러나 이는 커널에 힌트만 제공하여 PostgreSQL의 공유 버퍼로 직접 데이터를 가져오지는 못했습니다. -
PostgreSQL 18의 직접 페치: PostgreSQL 18은 이 간접적인 방식을 제거하고, 데이터베이스 자체가 공유 버퍼로 직접 데이터를 가져와 커널 수준의 휴리스틱에 대한 의존도를 없애고 예측 가능하며 높은 처리량의 I/O 동작을 가능하게 합니다.
새로운 io_method 설정
PostgreSQL 18은 비동기 I/O 메커니즘을 제어하는 io_method라는 새로운 설정 매개변수를 도입했습니다.
-
io_method = sync: PostgreSQL 17과 동일하게 동기식으로 작동하며posix_fadvise()를 사용합니다. -
io_method = worker: 백그라운드에서 실행되는 전용 I/O 워커 프로세스를 활용합니다. 메인 백엔드 프로세스는 읽기 요청을 큐에 넣고, 워커가 커널과 상호 작용하여 데이터를 가져와 공유 버퍼에 전달합니다.io_workers설정으로 워커 수를 조정할 수 있습니다(기본값 3). -
io_method = io_uring: Linux 커널 5.1 이상에서 도입된 고성능 I/O 인터페이스인io_uring을 사용합니다. PostgreSQL과 커널 간의 공유 링 버퍼를 설정하여 시스템 호출 오버헤드를 최소화합니다. 가장 효율적인 옵션이지만, 최신 Linux 커널과 호환되는 파일 시스템이 필요합니다.
성능 벤치마크
AWS 환경에서 수행된 벤치마크 결과, io_method = worker 및 io_uring은 sync 방식 대비 콜드 캐시 읽기 성능에서 2-3배 향상을 보였습니다. 특히 io_uring은 가장 낮은 시스템 호출 오버헤드와 프로세스 조정 감소로 최고의 성능을 제공했습니다.
effective_io_concurrency 튜닝
effective_io_concurrency 설정은 이제 비동기 I/O 방식(worker 또는 io_uring)에서 PostgreSQL이 내부적으로 발행하는 비동기 사전 읽기 요청 수를 직접 제어합니다. 이는 io_combine_limit와 함께 최대 사전 읽기 = effective_io_concurrency × io_combine_limit 공식을 따릅니다. 기본값이 1에서 16으로 상향 조정되었습니다.
I/O 모니터링
비동기 I/O 환경에서는 백엔드 프로세스가 직접 I/O를 차단하지 않으므로, pg_stat_activity에서 IO / AioIoCompletion과 같은 새로운 대기 이벤트를 확인해야 합니다. io_uring 사용 시에는 I/O 활동이 PostgreSQL 측에서 직접 보이지 않을 수 있으므로, 새로운 pg_aios 뷰를 사용하여 진행 중인 I/O 요청의 내부 상태를 확인할 수 있습니다. EXPLAIN ANALYZE의 I/O 타이밍 정보 해석에도 주의가 필요합니다.