PostgreSQLのパーティショニングはバージョンアップごとに強化されてきています。
アプリケーションに合わせてデータアクセスを局所化できれば、データが成長しても性能を維持しやすくなります。
パーティションテーブル新規作成
既存のテーブルを変換する方法はなく、パーティションテーブルは新規作成する必要があるため、まず既存のテーブルをリネームしておきます。
また、自動カウントのIDを利用している場合にはsequenceもリネームすると良いでしょう。
ALTER TABLE comments RENAME TO comments_bak;
ALTER SEQUENCE comments_id_seq RENAME TO comments_id_seq_bak;
次に、ベースのスキーマをダンプします。
pg_dump -Upostgres -t comments_bak some_db > dump.sql
CREATE TABLE
のDDLを書き換えてパーティションテーブルを作成します。
CREATE TABLE public.comments (
id bigserial NOT NULL,
article_id bigint NOT NULL,
comment text NOT NULL,
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
) PARTITION BY RANGE (article_id);
PARTITION BY
句がパーティショニングの設定。用途に応じて設計が必要- idはPRIMARY KEYではなくなる。
bigserial
型にしておくことで、自動採番は機能する
既存のシーケンス番号をコピーしておきます。
SELECT setval('comments_id_seq', (SELECT last_value FROM comments_id_seq_bak));
パーティションの作成とリストア
実データを格納するパーティションを作成します。パーティションのパラメータも用途に応じて設計が必要です。
CREATE TABLE comments_100000 PARTITION OF comments FOR VALUES FROM (0) TO (100000);
CREATE TABLE comments_default PARTITION OF comments DEFAULT;
データをリストアします。個別のパーティションは操作する必要がなく、最初に作成したpartitioned tableを更新します。
INSERT INTO comments SELECT * FROM comments_bak;
適切に動作していることを確認できたら、旧テーブルと旧sequenceは削除できます。
ridgepoleでパーティション・テーブルを管理
partitioned tableは一部の制約を除くと普通のテーブルとほぼ同じであるため、 ridgepoleからもmigrateできます。
テスト環境など、ridgepoleがCREATE TABLE
を発行する場合にはパーティショニングでない一般のテーブルが作成されます。アプリケーションからは操作の違いはありません。
データが入った時点で、スキーマを一度ダンプしておく(ridgepole -e
)と良いでしょう。
カラムの追加・削除やインデックスはpartitioned tableに反映すると、自動的に各パーティションにも反映されます。
ただし、version 0.xの古いridgepoleを使用している再には注意が必要です。
--skip-drop-table
オプション(version 1.0以降のデフォルト挙動)を常に利用して、パーティション(上の例ではcomments_100000とcomments_default)を管理対象から除外する必要があります。
作業ミスで--skip-drop-table
を付け忘れるとパーティションが消えてデータが失われるため、一般のテーブルよりも注意が必要です。
なお、パーティショニングはテーブル管理に追加の手順が必要であるため、導入前に公式ドキュメントでよく理解しておきましょう。
Chuma Takahiro