PostgreSQL IOPS 부족, 데이터베이스 성능 저하의 근본 원인과 해결책

by DD
4개월 전
조회수 18

IOPS(Input/Output Operations Per Second) 부족으로 인해 PostgreSQL 쿼리 성능이 저하되는 현상 분석

인덱스(Index) 부실로 인해 불필요한 디스크 I/O가 발생하여 IOPS를 초과하는 문제점 지적

락(Lock) 문제커넥션 풀(Connection Pool) 고갈이 IOPS 부족으로 인한 부작용임을 설명

Autovacuum의 I/O 부하와 쿼리 패턴(Query Pattern) 분석을 통해 문제 해결의 실마리 제시

IOPS 부족으로 인한 성능 저하의 메커니즘

PostgreSQL에서 IOPS가 부족해지면, 블록 레이어(Block Layer)하드웨어 큐(Hardware Queue)에 I/O 요청이 쌓이면서 지연 시간이 급증한다. 특히, 3000 IOPS 제한에 도달하면, 3001번째 요청부터 대기하게 되면서 각 요청의 처리 시간이 기하급수적으로 증가한다. 이러한 현상은 쿼리 실행 시간을 늘리고, 락(Lock)을 더 오래 유지하게 만들어 시스템 전반의 성능 저하를 유발한다.

Autovacuum과 인덱스(Index) 유지보수의 I/O 부하

Autovacuum은 데드 튜플(Dead Tuple)을 정리하기 위해 인덱스를 순회하며, 이 과정에서 많은 I/O를 발생시킨다. 특히, 인덱스가 메모리에 적재되지 않은 경우, 디스크에서 페이지를 읽어와야 하므로 IOPS 부하가 가중된다. Autovacuum의 비용 기반 스로틀링(Cost-Based Throttling)은 I/O 상황을 고려하지 않기 때문에, 이미 IOPS가 포화된 상황에서는 Autovacuum 자체가 성능 저하의 원인이 될 수 있다.

잘못된 쿼리 패턴(Query Pattern)과 인덱스(Index)의 중요성

특정 쿼리 패턴은 인덱스를 사용하더라도 불필요한 디스크 I/O를 발생시켜 IOPS를 소모한다. 예를 들어, 인덱스를 통해 특정 account_id를 찾은 후, JSONB 필터링을 적용하는 경우, 인덱스 스캔 후 모든 행을 읽어와 필터링을 수행해야 한다. 이러한 쿼리는 수만 개의 행을 디스크에서 읽어오고(Disk Reads), 대부분을 버리면서 IOPS를 낭비한다. 따라서, 효율적인 인덱스 설계(Efficient Index Design)가 중요하다.

IO:DataFileRead와 로드 평균(Load Average)의 관계

PostgreSQL 백엔드가 IO:DataFileRead 상태에 있을 때, 로드 평균(Load Average)이 증가하는 현상은 디스크 I/O 병목 현상을 나타낸다. IO:DataFileRead는 read(2) 시스템 콜의 완료를 기다리는 상태를 의미하며, 이 상태의 프로세스는 CPU를 사용하지 않지만, 디스크 I/O로 인해 시스템 전체의 성능을 저하시킨다. 따라서, IOPS 부족 문제를 해결하기 위해서는 I/O 병목 현상(I/O Bottleneck)을 정확히 파악하고, 쿼리 최적화 및 인덱스 개선을 통해 I/O 부하를 줄여야 한다.

What happens inside Postgres when IOPS runs out