

# pg\$1partman 확장자를 사용하여 PostgreSQL 파티션 관리하기
<a name="PostgreSQL_Partitions"></a>

PostgreSQL 테이블 파티셔닝은 데이터 입력 및보고의 고성능 처리를 위한 프레임워크를 제공합니다. 대량의 데이터를 매우 빠르게 입력해야 하는 데이터베이스의 경우 파티셔닝을 사용합니다. 파티셔닝은 큰 테이블의 빠른 쿼리를 제공합니다. 파티셔닝은 I/O 리소스가 적기 때문에 데이터베이스 인스턴스에 영향을 주지 않고 데이터를 유지 관리하는 데 도움이 됩니다.

파티셔닝을 사용하면 데이터를 사용자 지정 크기의 청크로 분할하여 처리할 수 있습니다. 예를 들어, 시간별, 일별, 주별, 월별, 분기별, 연도별, 사용자 지정 또는 이러한 조합과 같은 범위의 시계열 데이터를 분할할 수 있습니다. 시계열 데이터 예제의 경우 테이블을 시간별로 분할한 경우 각 파티션에는 1시간의 데이터가 포함됩니다. 시계열 테이블을 일별로 분할한 경우 파티션에는 하루 분량의 데이터가 저장되는 식입니다. 파티션 키는 파티션의 크기를 제어합니다.

분할된 테이블에서 `INSERT` 또는 `UPDATE` SQL 명령을 사용하는 경우 데이터베이스 엔진은 데이터를 적절한 파티션으로 라우팅합니다. 데이터를 저장하는 PostgreSQL 테이블 파티션은 기본 테이블의 하위 테이블입니다.

데이터베이스 쿼리를 읽는 동안 PostgreSQL 최적화 프로그램은 쿼리 `WHERE` 절을 검사하고 가능한 경우 데이터베이스 스캔을 관련 파티션에만 보냅니다.

버전 10부터, PostgreSQL은 선언적 분할을 사용하여 테이블 분할을 구현합니다. 이를 네이티브 PostgreSQL 파티셔닝이라고도 합니다. PostgreSQL 버전 10 이전에는 트리거를 사용하여 파티션을 구현했습니다.

PostgreSQL 테이블 분할은 다음과 같은 기능을 제공합니다:
+ 언제든지 새 파티션을 만들 수 있습니다.
+ 가변 분할 영역 범위입니다.
+ 데이터 정의 언어(DDL) 문을 사용하여 분리 및 재연결 가능한 파티션

  예를 들어 분리 가능한 파티션은 주 파티션에서 기록 데이터를 제거하지만 분석을 위해 기록 데이터를 유지하는 데 유용합니다.
+ 새 파티션은 다음을 포함하여 상위 데이터베이스 테이블 속성을 상속합니다.
  + 인덱스
  + 파티션 키 열을 포함해야 하는 기본 키
  + 외래 키
  + 제약 점검
  + 참조
+ 전체 테이블 또는 각 특정 파티션에 대한 인덱스 생성

개별 파티션에 대한 스키마를 변경할 수 없습니다. 그러나 분할 영역에 전파되는 상위 테이블 (예: 새 열 추가) 을 변경할 수 있습니다.

**Topics**
+ [PostgreSQL pg\$1partman 확장 개요](#PostgreSQL_Partitions.pg_partman)
+ [pg\$1partman 확장 활성화](#PostgreSQL_Partitions.enable)
+ [create\$1parent 함수를 사용하여 파티션 구성](#PostgreSQL_Partitions.create_parent)
+ [run\$1maintenance\$1proc 함수를 사용하여 파티션 유지 관리 구성](#PostgreSQL_Partitions.run_maintenance_proc)

## PostgreSQL pg\$1partman 확장 개요
<a name="PostgreSQL_Partitions.pg_partman"></a>

PostgreSQL `pg_partman` 확장을 사용하여 테이블 파티션의 생성 및 유지 관리를 자동화할 수 있습니다. 자세한 내용은 `pg_partman` 문서의 [PG 파티션 관리자](https://github.com/pgpartman/pg_partman)를 참조하세요.

**참고**  
`pg_partman` 확장은 RDS for PostgreSQL 버전 12.5 이상에서 지원됩니다.

각 파티션을 수동으로 생성하지 않고 다음 설정으로 `pg_partman`을 구성합니다.
+ 분할할 테이블
+ 파티션 유형
+ 파티션 키
+ 분할 영역 세분성
+ 파티션 사전 생성 및 관리 옵션

PostgreSQL 분할 테이블을 만든 후, `create_parent` 함수를 호출하여 `pg_partman`에 등록합니다. 이렇게 하면 함수에 전달하는 파라미터를 기반으로 필요한 파티션이 생성됩니다.

`pg_partman` 확장은 예약된 시간에 호출하여 파티션을 자동으로 관리할 수 있는 `run_maintenance_proc` 함수도 제공합니다. 필요에 따라 적절한 파티션이 생성되도록 하려면 이 기능을 주기적으로 실행하도록 예약합니다(예: 매 시간). 파티션이 자동으로 삭제되게 할 수도 있습니다.

## pg\$1partman 확장 활성화
<a name="PostgreSQL_Partitions.enable"></a>

파티션을 관리하려는 동일한 PostgreSQL DB 인스턴스 내에 여러 개의 데이터베이스가 있는 경우 각 데이터베이스별로 별도로 `pg_partman` 확장을 활성화해야 합니다. 특정 데이터베이스에 대해 `pg_partman` 확장을 활성화하려면 파티션 유지 관리 스키마를 생성한 후 다음과 같이 `pg_partman` 확장을 생성합니다.

```
CREATE SCHEMA partman;
CREATE EXTENSION pg_partman WITH SCHEMA partman;
```

**참고**  
`pg_partman` 확장을 만들려면 `rds_superuser` 권한이 있는지 확인하세요.

다음과 같은 오류가 발생하면 계정에 `rds_superuser` 권한을 부여하거나 수퍼유저 계정을 사용하십시오.

```
ERROR: permission denied to create extension "pg_partman"
HINT: Must be superuser to create this extension.
```

`rds_superuser` 권한을 부여하려면 수퍼유저 계정으로 연결하고 다음 명령을 실행합니다.

```
GRANT rds_superuser TO user-or-role;
```

pg\$1partman 확장 사용 방법을 보여 주는 예제에서는 다음 예제 데이터베이스 테이블 및 파티션을 사용합니다. 이 데이터베이스는 타임스탬프를 기반으로 분할된 테이블을 사용합니다. `data_mart` 스키마에는 라는 열이 `events` 있는 테이블이 포함되어 `created_at`있습니다. 이 `events` 테이블에는 다음과 같은 설정이 포함되어 있습니다.
+  기본 키 `event_id` 및 `created_at`파티션을 안내하는 데 사용되는 열이 있어야 합니다.
+ `ck_valid_operation` 테이블 열에 대한 값을 `operation` 적용하는 CHECK 제약 조건.
+ 두 개의 외래 키. 하나는 외부 테이블을`fk_orga_membership)` `organization` 가리키고 다른 하나는 자체 참조 외래 키입니다.`fk_parent_event_id`
+ 두 개의 인덱스. 여기서 하나 (`idx_org_id`) 는 외래 키용이고 다른 인덱스 (`idx_event_type`) 는 이벤트 유형용입니다.

다음 DDL 명령문은 각 파티션에 자동으로 포함되는 이러한 객체를 만듭니다.

```
CREATE SCHEMA data_mart;
CREATE TABLE data_mart.organization ( org_id BIGSERIAL,
        org_name TEXT,
        CONSTRAINT pk_organization PRIMARY KEY (org_id)  
    );

CREATE TABLE data_mart.events(
        event_id        BIGSERIAL, 
        operation       CHAR(1), 
        value           FLOAT(24), 
        parent_event_id BIGINT, 
        event_type      VARCHAR(25), 
        org_id          BIGSERIAL, 
        created_at      timestamp, 
        CONSTRAINT pk_data_mart_event PRIMARY KEY (event_id, created_at), 
        CONSTRAINT ck_valid_operation CHECK (operation = 'C' OR operation = 'D'), 
        CONSTRAINT fk_orga_membership 
            FOREIGN KEY(org_id) 
            REFERENCES data_mart.organization (org_id),
        CONSTRAINT fk_parent_event_id 
            FOREIGN KEY(parent_event_id, created_at) 
            REFERENCES data_mart.events (event_id,created_at)
    ) PARTITION BY RANGE (created_at);

CREATE INDEX idx_org_id     ON  data_mart.events(org_id);
CREATE INDEX idx_event_type ON  data_mart.events(event_type);
```



## create\$1parent 함수를 사용하여 파티션 구성
<a name="PostgreSQL_Partitions.create_parent"></a>

`pg_partman` 확장을 활성화한 후에는 `create_parent` 함수를 사용하여 파티션 유지 관리 스키마 내에 파티션을 구성합니다. 다음 예에서는 `events`에서 만든 [pg\$1partman 확장 활성화run\$1maintenance\$1proc 함수를 사용하여 파티션 유지 관리 구성](#PostgreSQL_Partitions.enable) 테이블 예제를 사용합니다. `create_parent` 함수를 다음과 같이 호출합니다.

```
SELECT partman.create_parent( 
 p_parent_table => 'data_mart.events',
 p_control      => 'created_at',
 p_type         => 'range',
 p_interval     => '1 day',
 p_premake      => 30);
```

파라미터는 다음과 같습니다.
+ `p_parent_table` – 상위 분할 테이블입니다. 이 테이블은 이미 존재해야 하며 스키마를 포함하여 정규화되어야 합니다.
+ `p_control` – 분할이 기반으로되는 열입니다. 데이터 유형은 정수 또는 시간 기반이어야 합니다.
+ `p_type` - 유형은 `'range'` 또는 `'list'`입니다.
+ `p_interval` – 각 파티션에 대한 시간 간격 또는 정수 범위입니다. 값의 예로는 `1 day`, `1 hour` 등이 포함됩니다.
+ `p_premake` – 새 삽입을 지원하기 위해 미리 생성할 분할 영역 수입니다.

`create_parent` 함수에 대한 자세한 설명은 `pg_partman` 설명서에서 [생성 함수](https://github.com/pgpartman/pg_partman/blob/master/doc/pg_partman.md#user-content-creation-functions)를 참조하세요.

## run\$1maintenance\$1proc 함수를 사용하여 파티션 유지 관리 구성
<a name="PostgreSQL_Partitions.run_maintenance_proc"></a>

파티션 유지 관리 작업을 실행하여 자동으로 새 파티션을 생성하거나, 파티션을 분리하거나, 이전 파티션을 제거할 수 있습니다. 파티션 유지 관리에는 내부 스케줄러를 시작하는 `pg_partman` 확장 및 `pg_cron` 확장의 `run_maintenance_proc` 함수가 사용됩니다. `pg_cron` 스케줄러는 데이터베이스에 정의된 SQL 문, 함수 및 프로시저를 자동으로 실행합니다.

다음 예제에서는 에서 만든 `events` 테이블 예제를 [pg\$1partman 확장 활성화run\$1maintenance\$1proc 함수를 사용하여 파티션 유지 관리 구성](#PostgreSQL_Partitions.enable) 사용하여 파티션 유지 관리 작업이 자동으로 실행되도록 설정합니다. 전제 조건으로 `pg_cron`을 DB 인스턴스의 파라미터 그룹의 `shared_preload_libraries` 파라미터에 추가합니다.

```
CREATE EXTENSION pg_cron;

UPDATE partman.part_config 
SET infinite_time_partitions = true,
    retention = '3 months', 
    retention_keep_table=true 
WHERE parent_table = 'data_mart.events';
SELECT cron.schedule('@hourly', $$CALL partman.run_maintenance_proc()$$);
```

다음으로, 앞의 예제에 대한 단계별 설명을 찾을 수 있습니다.

1. DB 인스턴스와 연결된 파라미터 그룹을 수정하고 `pg_cron` 파라미터 값에 `shared_preload_libraries` 추가합니다. 이 변경 사항을 적용하려면 DB 인스턴스를 다시 시작해야 합니다. 자세한 내용은 [Amazon RDS에서 DB 파라미터 그룹의 파라미터 수정](USER_WorkingWithParamGroups.Modifying.md) 섹션을 참조하세요.

1. `CREATE EXTENSION pg_cron;` 권한이 있는 계정을 사용하여 `rds_superuser` 명령을 실행합니다. 이렇게 하면 `pg_cron` 확장이 활성화됩니다. 자세한 내용은 [PostgreSQL pg\$1cron 확장을 사용하여 유지 관리 예약](PostgreSQL_pg_cron.md) 섹션을 참조하세요.

1. `UPDATE partman.part_config` 명령을 실행하여 `data_mart.events` 테이블에 대한 `pg_partman` 설정을 조정합니다.

1. `SET` 명령을 실행합니다. `data_mart.events` 테이블을 구성하려면 다음 절을 함께 사용합니다.

   1. `infinite_time_partitions = true,` – 제한 없이 자동으로 새 파티션을 만들 수 있도록 테이블을 구성합니다.

   1. `retention = '3 months',` – 최대 보존 기간이 3개월이 되도록 테이블을 구성합니다.

   1. `retention_keep_table=true `– 보존 기간이 만료될 때 테이블이 자동으로 삭제되지 않도록 테이블을 구성합니다. 대신 보존 기간보다 오래된 파티션은 상위 테이블에서만 분리됩니다.

1. `SELECT cron.schedule` 명령을 실행합니다. `pg_cron` 함수를 호출하려면 이 호출은 스케줄러가 `pg_partman` 유지 관리 프로시저 `partman.run_maintenance_proc`를 실행하는 빈도를 정의합니다. 이 예제에서는 프로시저가 매 시간 실행됩니다.

`run_maintenance_proc` 함수에 대한 자세한 설명은 `pg_partman` 설명서에서 [유지 관리 함수](https://github.com/pgpartman/pg_partman/blob/master/doc/pg_partman.md#maintenance-functions)를 참조하세요.