テーブル・パーティショニングの導入

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