【RHEL9】PostgreSQL15とpg_partmanの導入

# 概要
pg_partmanの導入が必要になってので手順メモです。

pg_partmanは、時間ベースおよび数値ベースのテーブルパーティションセットを作成および管理するためのPostgreSQLの拡張機能です。特に、時間が経過するにつれて子テーブルのメンテナンス（新しい子テーブルの追加、保持ポリシーに基づく古いものの削除など）を自動化する方法を提供しています。

### 環境
- OS : Miracle Linux 9.1
- PostgreSQL : 13 → 15
- pg_partman : v5.0.1

# 手順
## PostgreSQL15の導入
RHEL9ではdnfモジュールでPostgreSQL15が導入できるのでそれを使います。

:::note warn
必要に応じて既存のPostgreSQLのdump取得と削除しておいたほうがシンプルです。一応、postgresql-upgradeを使えばバージョンアップも出来ます。
:::

```
# dnf module list postgresql
>> PostgreSQL15のStreamがあることを確認
# dnf enable postgresql:15
>> PostgreSQL15のストリームを有効化
# dnf install postgresql-server postgresql-server-devel postgresql-contrib
>> PostgreSQL15のインストール
```

適宜、PostgreSQLのunitファイルを編集し```PG_DATA```などの値を変更して、PostgreSQLの初期セットアップを実施します。

```
// unitファイルを編集する場合はetc配下にコピーを配置
# cp -p /lib/systemd/system/postgresql.service /etc/systemd/system/postgresql.service
# vi /etc/systemd/system/postgresql.service
>> PG_DATAなどの値を適宜編集する
# systemctl daemon-reload
// initdbでデータベースを初期化する
# su postgres
$ /usr/bin/initdb -D [PG_DATAディレクトリ(省略可)] --encoding=UTF-8
```

インストールと初期設定が完了したら、```psql --version```でバージョンが上がっていることを確認しておく
```
# psql --version
psql (PostgreSQL) 15.5
```

## pg_partmanの導入
まず、公式のリポジトリをクローンしソースコードを取得する

https://github.com/pgpartman/pg_partman.git

```
# cd /usr/local/src
# git clone https://github.com/pgpartman/pg_partman.git
```

ソースをmake installしてコンパイルする。
```
# cd pg_partman
# make install
>> エラーなく完了したらPostgreSQLのextensionディレクトリに追加されていることを確認
# ls -al /usr/share/pgsql/extension/pg_partman.control 
-rw-r--r-- 1 root root 111  2月 27 10:40 /usr/share/pgsql/extension/pg_partman.control
```

pg_partmanを拡張機能として読み込むように```postgresql.conf```を設定する
```:postgresql.conf
// 設定を追加
shared_preload_libraries = 'pg_partman_bgw'
```

設定を反映するため、PostgreSQLを再起動する

```
# systemctl restart postgtesql
```

pg_partmanを有効にしたいテーブルで拡張機能を設定する。
※ 今回は```pg_partman_test```というテーブルで実施

```
# psql -U postgres
postgres=# create table pg_partman_test
CREATE TABLE
postgres=# \c pg_partman_test
>> pg_partman用のスキーマと拡張機能とを設定
pg_partman_test=# CREATE SCHEMA partman;
CREATE SCHEMA
pg_partman_test=# CREATE EXTENSION pg_partman SCHEMA partman;
CREATE EXTENSION
pg_partman_test=# \dx
                                 インストール済みの拡張一覧
    名前    | バージョン |  スキーマ  |                         説明                         
------------+------------+------------+------------------------------------------------------
 pg_partman | 5.0.1      | partman    | Extension to manage partitioned tables by time or ID
 plpgsql    | 1.0        | pg_catalog | PL/pgSQL procedural language
```

ここまでで、pg_partmanの基本的な設定は完了です。

次に権限の設定を実施します。
pg_partmanの機能を利用するためには、**実際にテーブルを操作するロールに対して、対象テーブルに作成した```partman```スキーマに対して各権限が必要になります。**

なので、実際に作業をするロールに対して以下の権限を付与します。

:::note warn
スーパーユーザーを使う場合は不要ですが、一般的に考えればスーパーユーザーを使うべきではありません。
:::

```
pg_partman_test=# ALTER DATABASE pg_partman_test OWNER TO user01
pg_partman_test=# GRANT ALL ON SCHEMA partman TO user01;
pg_partman_test=# GRANT ALL ON ALL TABLES IN SCHEMA partman TO user01;
pg_partman_test=# GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA partman TO user01;
pg_partman_test=# GRANT EXECUTE ON ALL PROCEDURES IN SCHEMA partman TO user01;
```

## 動作検証
以下の公式Howtoに基づいて動作検証を実施します。

https://github.com/pgpartman/pg_partman/blob/master/doc/pg_partman_howto.md#undoing-native-partitioning

### テーブルの作成
まず、親となるパーティションテーブルを作成します。
```
CREATE SCHEMA IF NOT EXISTS partman_test;

CREATE TABLE partman_test.time_taptest_table
    (col1 int,
    col2 text default 'stuff',
    col3 timestamptz NOT NULL DEFAULT now())
PARTITION BY RANGE (col3);

CREATE INDEX ON partman_test.time_taptest_table (col3);
```

### テンプレートテーブルの作成
pg_partmanはパーティションを管理するためにテンプレートテーブルを使用します。

```
CREATE TABLE partman_test.time_taptest_table_template (LIKE partman_test.time_taptest_table);

ALTER TABLE partman_test.time_taptest_table_template ADD PRIMARY KEY (col1);
```

### create_parent()関数の実行
create_parent関数を実行すると、指定された親テーブルに対して指定したテンプレートテーブルに基づきパーティションが作成されます。
```
SELECT partman.create_parent(
    p_parent_table := 'partman_test.time_taptest_table',
    p_control := 'col3',
    p_interval := '1 day',
    p_template_table := 'partman_test.time_taptest_table_template'
);
```

### パーティションが作成されていることの確認
create_parent関数によってパーティションが作成されていることを確認します。
```
 \d+ partman_test.time_taptest_table
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2420694/58a2fcc0-f072-07fa-76b3-2543c9e33894.png)

# まとめ
一旦導入までしただけなので、これで十分に動くかは要検証かなと思います。pg_partmanを使ったパーティション管理の方法については色々とやり方を覚えないと大変そう。関数や設定値など、必要なことをドキュメントで確認して、十分に検証を行った上で使うことをおすすめします。

https://github.com/pgpartman/pg_partman/blob/master/doc/pg_partman.md

気が向いたら機能的な部分もまとめてみようと思います。