- PostgreSQL 18は、ファイル複製戦略(FILE_COPY) と ファイルシステムのクローン機能を組み合わせることで、データベースをほぼ即時に複製できる
- 新しい設定値
file_copy_method = clone を使うと、XFS、ZFS、APFS など 現代的なファイルシステムの複製機能(FICLONE) を活用可能
- ベンチマーク結果では、6GBのデータベースを複製する際、従来の WAL_LOG方式は約67秒、クローン方式は 0.2秒程度 まで短縮
- 複製されたデータベースは、初期状態では同じ物理ブロックを共有するが、書き込み時には copy-on-write で分離される
- ただし、アクティブな接続がない状態でのみ複製可能であり、単一ファイルシステム内でのみ動作するという制約がある
PostgreSQLのテンプレートベース複製構造
- PostgreSQLは
CREATE DATABASE dbname コマンド実行時、内部的に template1 データベースを複製して新しいデータベースを作成する
- これは
CREATE DATABASE dbname TEMPLATE template1 と同じ動作
template1 の代わりに別のデータベースを指定できるため、ユーザー定義テンプレートを使った複製も可能
- PostgreSQL 18では、このテンプレートシステムを 即時複製可能な構造へと拡張
CREATE DATABASE ... STRATEGY
- PostgreSQL 15から
CREATE DATABASE ... STRATEGY パラメータが導入され、複製方式を選択できる
- デフォルトは
WAL_LOG で、Write-Ahead Logによるブロック単位の複製を行う
- この方式は I/O負荷を減らし同時実行性のサポートを改善する一方、大容量複製では速度が遅い
STRATEGY=FILE_COPY を指定すると 従来のファイルコピー方式に戻せ、PostgreSQL 18ではこれを基盤として 新しい複製オプションが追加された
FILE_COPYとfile_copy_method
- PostgreSQL 18の
file_copy_method 設定は、OSレベルのファイル複製方式を制御する
- デフォルトは
copy で、すべてのバイトを読み込んで新しい場所に書き込む
clone に変更すると、ファイルシステムのクローン機能(FICLONE) を使って 即時複製かつ追加の容量消費なしで動作する
- 対応ファイルシステム: XFS、ZFS、APFS、FreeBSD ZFS
- 設定手順
- 対応するファイルシステム上に PostgreSQL クラスターを構成
file_copy_method = clone を設定してリロード
ベンチマーク結果
- 約6GBのテストデータベース(
source_db)を作成後、2つの方式を比較
WAL_LOG 方式: 67,000ms(約67秒)
FILE_COPY + clone 方式: 212ms
- 同じデータサイズで 約300倍以上の高速化 を確認
- 複製されたデータベース(
fast_clone)は、追加のディスク容量をほとんど消費しない
複製データの動作原理
file_copy_method = clone を使うと、ファイルシステムのメタデータだけが複製され、2つのデータベースが 同じ物理ブロックを共有する
- PostgreSQLが報告するデータベースサイズは論理サイズ(約6GB)として同一
- 書き込みが発生すると copy-on-write(COW) が動作し、該当ページが分離される
- 変更された行を含むページ
- 新しいタプルが書き込まれるページ
- インデックスページ、FSM、visibility mapページなど
- VACUUM実行時にも追加のページ分離が発生する
XFSでの共有ブロック検証
filefrag -v コマンドで 2つのデータベースが物理ブロックを共有しているか を確認
- 初期状態ではすべての extents が
shared と表示される
- 一部の行を更新すると、先頭40ブロック(約160KB)が分離され、異なる物理アドレスに変わる
- 残りの extents は引き続き共有状態を維持
注意事項と制約
- 複製時には元データベースにアクティブな接続があってはならない
- これはPostgreSQLの制約であり、ファイルシステムの問題ではない
- 本番サービス環境では、専用のテンプレートデータベースを使うのが一般的
- 単一ファイルシステム内でのみ複製可能
- 複数のテーブルスペースが異なるマウントポイントにある場合は、通常コピーに置き換えられる
- クラウドのマネージドサービス(AWS RDS、Google Cloud SQL など) ではファイルシステムへアクセスできないため、この機能は利用不可
結論
- PostgreSQL 18の
file_copy_method = clone 機能は、OSレベルのクローン機能を直接活用することで、
大容量データベースの複製時間を劇的に短縮する
- テスト、開発、学習環境で 即時複製とリセット可能なデータベースワークフロー を実現できる
- ただし、アクティブ接続の制約と単一ファイルシステムという条件を考慮した運用設計が必要
1件のコメント
Hacker Newsの反応
PG18 を待てない人や、完全なインスタンス分離が必要な人向けに、ZFSスナップショットを使って即時ブランチを作成するツール Velo を作った
どの PostgreSQL バージョンでも動作し、各ブランチは独立したコンテナとポートを持つ
100GB の DB でも約 2〜5 秒で作成できる
PG18 の方式との違いは、単一インスタンスを共有せず、完全なサーバー分離を提供する点
GitHubリンク
以前、会社が RDS に移行したとき、似たような仕組みを自前で構築した
本番マイグレーション中によく問題が起きたので、それを防ぐために次の手順を自動化した
この流れのおかげで、ローカルや CI では見つからなかった 本番特有のバグ を多く発見できた
その後、簡単な Rubyスクリプト で自動化し、今でもそのスクリプトが使われていると聞いている
テンプレートクローン 戦略が設定可能だということを今回初めて知った
自分は Neon を使ってリアルタイム統合環境を作っていて、Golangプロジェクト pgtestdb では各テストごとに完全なスキーママイグレーションが適用された Postgres DB を生成している
以前スタートアップで btrfs を使って即時ステージング DB を作るのを見たことがあり、こうした似たアイデアが何度も現れるのは興味深い
このような 高速複製とテスト は Postgres と Sqlite の大きな利点で、Clickhouse や MySQL でも可能になってほしい
最近の PostgreSQL は、ほぼあらゆる SQL の用途をカバーする万能 DB になったように見える
しかも 無料 だ
もう他の SQL DB を使う理由があるのだろうかと思う
Clickhouse は分析用途でははるかに高速で、Cassandra のような DB は書き込み中心のワークロードに向いている
つまり、各 DB には今でもそれぞれ強みがある
データが増えると 性能低下 や マイグレーションの問題 が起きる
自分の場合、標準のパーティショニング性能が低くて、自前でカスタムパーティションを実装しなければならなかった
この選択が高負荷時にいくつもの悪影響を生む
Uberのブログ記事でも扱われていた話題だ
それでもクラウド環境では Postgres を最も信頼している
そのため大規模な OLTPデプロイ では、今でも主に MySQL が使われている(例: YouTube, Uber)
不変データ構造(HAMT) を使えば、ファイルシステムの種類に関係なく即時クローン可能な DB を作れる
理論の話だと言っていたが、実際に実装してみた
なぜこうした HAMTベースのDB がもっと増えないのか理解できない
関連ドキュメント
Postgres v15 で WAL_LOG がデフォルトに変わっていたことを知らなかった
並列 CI テスト環境では FILE_COPY 戦略に戻すほうが合理的だ
以前のプロジェクト integresql に関連 issue を上げたことがある
ローカルで Postgres ベースのアプリをテストするためのシンプルな GUIツール pgtt を作ったことがある
開発環境のセットアップをかなり単純化してくれる
SQL マイグレーションの繰り返し作業に役立ちそうだ
ブログの他の記事も読んでみたが、全体的に素晴らしい
特に Postgres の range 型 を初めて知った
MariaDB にもこういう機能があるのか気になる
テストごとに DB を初期状態へ戻すのが遅くて悩んでいる
本番では MariaDB を使っているので、DB を変えるのは難しい
Postgres のほうが良さそうには見える
この方法はかなり効率的だ
AWS でも類似機能を提供している
Auroraクローンのドキュメント
統合テスト用途としては現実的ではない