pg_partman을 사용한 대규모 시계열 데이터용 PostgreSQL 파티셔닝 자동화
Lukas Schneider
DevOps Engineer · Leapcell

소개
빅데이터 시대에 끊임없이 증가하는 데이터셋을 관리하는 것은 특히 시계열 정보를 다룰 때 중요한 과제입니다. IoT 센서 판독값, 금융 거래 기록 또는 네트워크 원격 측정 데이터와 같은 데이터셋은 빠르게 기가바이트, 테라바이트, 심지어 페타바이트까지 증가할 수 있습니다. 데이터 볼륨이 증가함에 따라 이러한 테이블을 쿼리, 보관 및 유지 관리하는 복잡성도 증가합니다. 단일 모놀리식 테이블에 데이터를 단순히 추가하면 필연적으로 성능 저하, 진공 오버헤드 증가 및 인덱스 재빌드 시간 연장으로 이어집니다. 여기서 데이터베이스 파티셔닝이 등장하며, 특정 기준(종종 시간)에 따라 대규모 테이블을 더 작고 관리 가능한 조각으로 분할하는 전략을 제공합니다. PostgreSQL은 네이티브 파티셔닝 기능을 제공하지만, 수천 개의 파티션(생성, 삭제 및 인덱싱 포함)을 수동으로 관리하는 것은 관리 작업을 악몽으로 만듭니다. 이 글에서는 pg_partman에 대해 자세히 알아봅니다. 이 확장 기능은 이 프로세스를 자동화하도록 설계되어 PostgreSQL에서 매우 큰 시계열 데이터 테이블의 관리를 효율적이고 실질적으로 가능하게 합니다.
시계열 데이터 관리 이해
pg_partman을 자세히 살펴보기 전에, 유용성을 이해하는 데 필수적인 몇 가지 핵심 개념을 명확히 하겠습니다.
- 시계열 데이터: 시간별로 인덱싱된 데이터 포인트로, 일반적으로 일정 기간 동안 수집됩니다. 일반적인 특징은 높은 삽입 속도, 추가 전용 특성(또는 드문 업데이트), 종종 시간 범위로 필터링되는 쿼리입니다.
- 데이터베이스 파티셔닝: 대규모 논리적 테이블을 파티션이라는 더 작은 물리적 조각으로 분할하는 기술입니다. PostgreSQL에서는 일반적으로
RANGE또는LIST파티셔닝을 사용하여 수행됩니다. 시계열 데이터의 경우, 타임스탬프 열에 대한RANGE파티셔닝이 가장 일반적인 접근 방식이며 특정 시간 간격(예: 일별, 주별, 월별)에 대한 파티션을 생성합니다. - 선언적 파티셔닝: PostgreSQL 10부터
PARTITION BY RANGE또는PARTITION BY LIST를 사용하여CREATE TABLE문에서 직접 파티셔닝을 정의할 수 있습니다. 그런 다음CREATE TABLE ... PARTITION OF ...를 사용하여 하위 파티션이 생성됩니다. - 파티션 가지치기(Pruning): 쿼리 플래너가 쿼리의
WHERE절을 조사하고 관련 데이터가 포함되지 않은 파티션을 제거(가지치기)하여 스캔하는 데이터 양을 크게 줄이는 최적화입니다. - 보존 정책: 데이터가 얼마나 오래 보관되어야 하는지를 정의하는 규칙 집합입니다. 시계열 데이터의 경우, 오래된 데이터는 관련성이 떨어지거나 더 저렴한 스토리지로 이동해야 하는 경우가 많으므로 강력한 보관 및 제거 메커니즘이 필요합니다.
pg_partman은 이러한 선언적 파티션의 라이프사이클 관리를 자동화하는 격차를 해결합니다. PostgreSQL은 구성 요소를 제공하지만, pg_partman은 파티션 생성, 만료 및 인덱싱을 조정하여 관리자가 지루한 수동 작업에서 벗어날 수 있도록 합니다.
pg_partman 작동 방식
pg_partman은 관리하는 각 상위 테이블에 대한 파티셔닝 구성을 정의하는 메타데이터 테이블(partman.part_config)을 유지하여 작동합니다. 이 구성에 따라 지정된 보존 정책에 따라 동적으로 향후 파티션을 생성하고 오래된 파티션을 삭제합니다. 일반적으로 예약된 작업(예: cron을 통해)으로 실행됩니다.
시계열 테이블에 대해 pg_partman을 설정하는 방법을 예시를 통해 살펴보겠습니다.
1. pg_partman 설치
먼저 확장 기능을 설치해야 합니다. 일반적으로 패키지를 설치하고(예: Debian/Ubuntu의 postgresql-14-partman) 데이터베이스 내에서 활성화해야 합니다.
CREATE EXTENSION pg_partman;
2. 상위 테이블 생성
센서 판독값을 저장하는 sensor_data 테이블과 timestamp 열이 있다고 가정해 보겠습니다.
CREATE TABLE public.sensor_data ( id BIGSERIAL NOT NULL, sensor_id INT NOT NULL, measurement_value NUMERIC(10, 2) NOT NULL, event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW() ) PARTITION BY RANGE (event_timestamp); -- 초기 기본 파티션을 생성하는 것은 정의된 파티션 범위에 속하지 않는 모든 데이터에 대한 좋은 습관입니다. CREATE TABLE public.sensor_data_default PARTITION OF public.sensor_data DEFAULT;
'PARTITION BY RANGE (event_timestamp)' 절에 주목하세요. 이는 sensor_data가 event_timestamp 열을 기반으로 하는 파티션된 테이블임을 PostgreSQL에 알립니다.
3. pg_partman 구성
이제 pg_partman에 public.sensor_data를 관리하도록 지시합니다. 일별 파티션을 설정하고 5일 후를 미리 만들며 데이터를 30일간 보존합니다.
SELECT partman.create_parent( p_parent_table => 'public.sensor_data', p_control_column => 'event_timestamp', p_interval => 'daily', p_premake => '5 days', p_retention => '30 days' );
이 매개변수를 자세히 살펴보겠습니다.
p_parent_table: 상위 테이블의 스키마와 이름(public.sensor_data).p_control_column: 파티셔닝에 사용되는 열(event_timestamp).p_interval: 각 파티션의 기간(daily). 다른 옵션으로는'hourly','weekly','monthly','yearly'또는'3 hours','15 minutes'와 같은 특정 시간 간격이 있습니다.p_premake:pg_partman이 빈 파티션을 얼마나 미리 생성해야 하는지.'5 days'는 향후 5일 동안 파티션을 생성한다는 의미입니다. 이렇게 하면 새 데이터가 지연 없이 항상 들어갈 파티션이 있게 됩니다.p_retention: 파티션이 얼마나 오래 유지되어야 하는지.'30 days'는 30일보다 오래된 파티션이 삭제된다는 의미입니다.
create_parent를 실행한 후, pg_partman은 즉시 첫 번째 하위 파티션 세트를 생성합니다.
\d+ public.sensor_data
sensor_data_2023_10_26, sensor_data_2023_10_27 등과 같은 결과가 표시됩니다.
4. 유지 관리 함수 실행
pg_partman의 자동화 핵심은 유지 관리 함수에 있습니다. 이 함수는 주기적으로 호출해야 합니다.
SELECT partman.run_maintenance();
run_maintenance()를 실행하면 partman.part_config 테이블을 기반으로 여러 작업을 수행합니다.
- 새 파티션 생성:
p_premake를 확인하고 필요한 미래 파티션을 생성합니다. - 오래된 파티션 삭제:
p_retention을 확인하고 지정된 보존 기간보다 오래된 파티션을 삭제합니다. 이는 스토리지 및 성능 관리에 중요합니다. - 파티션 연결: 비파티션된 테이블에 기존 데이터가 있는 경우,
pg_partman은 이를 연결하는 데 도움을 줄 수 있습니다. - 인덱스 관리: 상위 테이블의 인덱스 정의를 기반으로 새 파티션에 인덱스를 자동으로 생성할 수 있습니다.
5. 유지 관리 예약
run_maintenance() 호출은 정기적으로 실행되도록 예약해야 합니다. 일반적인 방법은 데이터베이스 서버의 cron 또는 전용 스케줄러를 사용하는 것입니다. 예를 들어, 매시간 실행하려면:
# crontab (예: `crontab -e`)에서 0 * * * * psql -d your_database -c "SELECT partman.run_maintenance();"
애플리케이션 시나리오 및 고급 기능
- 기존 데이터 마이그레이션:
pg_partman은 기존 데이터를 비파티션된 테이블에서 새로 생성된 파티션된 자식 테이블로 이동하는 함수를 제공합니다. - 사용자 정의 명명 규칙: 기본
tablename_YYYY_MM_DD형식이 적합하지 않은 경우 사용자 지정 하위 파티션 이름을 지정할 수 있습니다. - 인덱스 관리:
pg_partman은 상위 테이블을 미러링하는 새 파티션에 인덱스를 생성하도록 구성할 수 있습니다. 이는 쿼리 성능에 필수적입니다. - "템플릿: 더 복잡한 파티셔닝 구성이나 새 파티션에 특정 테이블/인덱스 저장 매개변수를 적용하기 위해
pg_partman은 템플릿 테이블을 지원합니다. - 백그라운드 워커: 매우 활동적인 시스템의 경우,
pg_partman은 외부 스케줄링 문제를 피하기 위해 PostgreSQL 내에서 백그라운드 워커 프로세스로 실행될 수도 있습니다. - 파티션 아카이빙: 오래된 파티션을 삭제하는 것 외에도,
pg_partman은 이를 분리하여 삭제하기 전에 콜드 스토리지로 이동하거나 보관할 수 있도록 구성할 수 있습니다.
이러한 프로세스를 자동화함으로써 pg_partman은 대규모 파티션된 테이블을 관리하는 운영 오버헤드를 크게 줄여 개발자와 DBA가 인프라 관리보다는 데이터 활용에 집중할 수 있도록 합니다. 파티션 가지치기를 활용하여 쿼리를 계속 성능이 뛰어나도록 보장하고 정기적인 데이터 가지치기를 통해 스토리지 성장을 제어합니다.
결론
적절한 자동화 없이 PostgreSQL에서 테라바이트 규모의 시계열 데이터를 관리하는 것은 성능 병목 현상과 관리 복잡성으로 가득 찬 힘든 싸움입니다. pg_partman은 강력한 라이프사이클 관리 기능을 통해 PostgreSQL의 네이티브 파티셔닝 기능을 원활하게 확장하는 필수 도구로 등장합니다. 수천 개의 파티션 생성, 보존 및 유지 관리를 단순화하여 최적의 데이터베이스 성능과 예측 가능한 스토리지 비용을 보장합니다. 대규모 시간 기반 데이터를 다루는 모든 PostgreSQL 배포판의 경우, pg_partman은 편의성뿐만 아니라 확장 가능하고 유지 관리 가능한 운영을 위한 필수 요소입니다.

