대용량 자료 입력용 임시 서버 환경 설정

대용량 입력 작업을 가볍게

일반적으로 pg_dump 작업 결과물을 다시 데이터베이스에 넣는 작업은 꽤 많은 대량의 데이터베이스 입력 작업이 일어납니다. 

근원적으로 가장 먼저 OS 파일시스템의 I/O 성능을 최대화 할 수 있는 튜닝이 먼저 되어야겠지만, 이 부분은 이 글의 범위를 벗어나서 여기서는 postgresql.conf 파일을 수정해서 데이터베이스 자료 입력 성능을 최대화 하는 부분만을 살펴보겠습니다. 

환경 설정 바꾸기

이 글은 데이터베이스 자료 입력 성능에 관계된 환경 설정 매개변수들을 소개하는 것입니다. 즉 아래에서 설명하는 여러 환경 설정 값들을 변경하고 그것을 적용하기 위해서 재실행 할 수 있는 운영 환경에서 적용 가능한 이야기입니다. 
또한, 일반적인 운영 환경으로 되돌아 가기 위해서, 반드시 원본 postgresql.conf 파일은 작업 전 따로 보관해 두는 것이 안전할 것입니다.

fsync = off

데이터베이스에서 디스크 쓰기가 일어나는 작업은 데이터 파일(global, base 디렉토리 안에 있는 파일들)과 트랜잭션 로그 조각 파일 (pg_xlog 디렉토리 안에 있는 파일)을 새로 만들거나 갱신하는 경우가 대부분입니다. 물론 그외 pg_log 디렉토리에서 보관되는 서버 로그 파일도 있고, 통계정보가 임시로 보관되는 pg_stat_tmp 쪽에서도 빈번하게 디스크 I/O가 발생하지만, 역시 pg_xlog와 base 디렉토리 안에 있는 파일의 I/O가 데이터베이스 서버의 디스크 성능에 가장 밀접한 영향을 끼칩니다.

이 설정은 이 디스크 쓰기에 대해서 해당 호스트의 물리적인 디스크 쓰기에 대한 기능을 결정하는 중요한 설정입니다. off 로 설정하면 OS의 디스크 버퍼까지만 기록해도 디스크 쓰기를 완료했다고 처리합니다. 그 만큼 디스크 쓰기가 서버 입장에서는 빠르겠죠.

synchronous_commit = off

PostgreSQL에서 트랜잭션은 그 테이블이 unlogged 옵션을 사용해서 만들지 않았다면, 반드시 그 트랜잭션 내용을 트랜잭션 로그에 먼저 쓰고(write ahead) 공유 버퍼에 있는 데이터 페이지에 기록합니다. 

그 트랜잭션이 commit 되었다면, 자료의 안전한 보관을 위해 반드시 트랜잭션 로그 조각 파일(pg_xlog 디렉토리 안에 있는 파일)에 그 트랜잭션 내용이 기록되어야 합니다.

이 처리의 확인 범위를 어디까지 할 것인가? 이 부분을 결정하는 설정값입니다. off로 설정하면, 트랜잭션 로그 버퍼(wal_buffer 라고 합니다)까지만 기록되면 트랜잭션 로그를 기록했다고 간주하는 것이고, on으로 설정하면, OS의 디스크 버퍼까지 기록함을 의미합니다. 물론 fsync 설정값이 off가 아니라면, 물리적인 디스크까지 기록함을 의미하겠죠. 

윗 두 설정을 모두 off로 설정함은 서버의 데이터 안정성을 보장하지 않음을 의미합니다. 정확하게 이야기하면, 트랜잭션 로그 버퍼에는 자료가 있고, 그것이 이미 commit 되었음에도 불구하고, 시스템 장애로 서버가 재실행된다면, 미처 기록하지 못한 내용들은 모두 손실됨을 주의해야 합니다.

full_page_writes = off

윗 두 설정을 off 한다는 것은 위에서 언급한 것처럼 서버 비정상적 종료 상황에서 자료 유실을 감안하겠다는 것을 의미합니다. 이런 경우라면, 이 기능 또한 켜두어야 할 필요는 없습니다. 

이 설정값을 on 으로 설정하면, (기본값이 on) 체크 포인트 다음 그 해당 데이터 페이지의 첫 변경분은 무조건 그 페이지 전체를 트랜잭션 로그에 기록합니다. off로 설정하면 트랜잭션 로그 리두 작업을 할 때, 데이터 페이지가 손상되지 않았다는 것을 전제하는 샘입니다. 

checkpoint_segments = 아주크게

이 설정값은 지정한 수 * 16MB 만큼의 트랜잭션 로그를 보관합니다. 물론 내부적으로 원활한 트랜잭션 로그 조각 파일의 재활용을 위해서 디스크 여유 공간이 있는 한 그 수의 1.5배 만큼의 파일을 사용합니다. 즉, 이 값이 8이라면, 20개 정도의 트랜잭션 로그 조각 파일이 생깁니다. 

이글의 촛점인 대용량 자료 입력을 위해서라면, 새로운 트랜잭션 로그 조각 파일을 만들지 않도록 기존 파일을 재활용할 수 있도록 이 값을 OS가 허용하는 한 크게 설정합니다. 

작업 전 txid_crruent(), pg_switch_xlog() 함수를 함께 호출해서 미리 충분한 트랜잭션 로그 조각 파일들을 확보하는 것도 좋은 방법입니다.

maintenance_work_mem = 허용하는최대크기

이 설정값은 CREATE INDEX 작업에서 최대한 메모리를 유용하게 쓸 때 조정합니다. 대량 자료가 입력된 뒤 대부분 후속 작업으로 그 자료에 대한 인덱스 작업을 하게 됩니다. 이 때 최대한 디스크 I/O를 줄이는 방법으로 이 값을 OS의 물리적 메모리가 허용하는 최대로 설정합니다.

wal_level = minimal, archive_mode = off

아카이브 모드를 사용하고 있다면, 이 기능을 잠시 끄면 디스크 I/O를 상당량 줄일 수 있습니다.

autovacuum = off

당연히 작업 도중 vacuum 작업이 자동으로 진행되지 않도록 하는 것도 빼먹지 말아야 겠죠. 또한 작업이 끝나면, analyze 작업이 필요하다는 사실도 함께.

마무리

글을 정리하면서 보니, 지극히 평범한 글이 되어버렸습니다. 핵심은 대용량 입력 작업의 성능을 극대화 하는 서버 환경 설정 최적화 방법은 디스크 I/O를 줄이는 방법이 최선이며 이에 대해서 간단하게 살펴보았습니다. 

이 글에서 빠졌는 부분은 pg_dump 결과물이 pg_restore 명령으로 복원작업을 한다면, -j 옵션을 이용한 OS의 멀티코어 환경을 고려하는 것도 좋은 방법입니다.