1 ポイント 投稿者 GN⁺ 2025-12-24 | 1件のコメント | WhatsAppで共有
  • 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 など) ではファイルシステムへアクセスできないため、この機能は利用不可
    • 自前のVMやベアメタル環境では完全に制御可能

結論

  • PostgreSQL 18の file_copy_method = clone 機能は、OSレベルのクローン機能を直接活用することで、
    大容量データベースの複製時間を劇的に短縮する
  • テスト、開発、学習環境で 即時複製とリセット可能なデータベースワークフロー を実現できる
  • ただし、アクティブ接続の制約と単一ファイルシステムという条件を考慮した運用設計が必要

1件のコメント

 
GN⁺ 2025-12-24
Hacker Newsの反応
  • PG18 を待てない人や、完全なインスタンス分離が必要な人向けに、ZFSスナップショットを使って即時ブランチを作成するツール Velo を作った
    どの PostgreSQL バージョンでも動作し、各ブランチは独立したコンテナとポートを持つ
    100GB の DB でも約 2〜5 秒で作成できる
    PG18 の方式との違いは、単一インスタンスを共有せず、完全なサーバー分離を提供する点
    GitHubリンク

    • 別のコメントでは Claude Code の使用に不満が出ていたが、GitHub ページのデモ動画を見て興味深いと感じた
    • 最近はほとんどのソフトウェアが AIエージェント の助けを借りて書かれているのに、なぜ文句が出るのかわからない。アプローチは興味深い
    • 自分もちょうど似たようなものを btrfs でプロトタイプしようとしていた
    • 「あなた」という表現が面白いと思っていたが、盗作だという話が出てきて少し驚いた
  • 以前、会社が RDS に移行したとき、似たような仕組みを自前で構築した
    本番マイグレーション中によく問題が起きたので、それを防ぐために次の手順を自動化した

    1. RDS DB を複製するか、バックアップから新しいインスタンスを作成
    2. ARN から CNAME またはパブリック IP を抽出
    3. アプリの DB 接続設定に反映
    4. 擬似本番環境でマイグレーションを実行
      この流れのおかげで、ローカルや CI では見つからなかった 本番特有のバグ を多く発見できた
      その後、簡単な Rubyスクリプト で自動化し、今でもそのスクリプトが使われていると聞いている
    • 自分もそういう「データの癖のせいで本番でしか失敗しないマイグレーション」バグは本当に嫌いだ。何度かそのせいでリリースを中止したこともある
  • テンプレートクローン 戦略が設定可能だということを今回初めて知った
    自分は Neon を使ってリアルタイム統合環境を作っていて、Golangプロジェクト pgtestdb では各テストごとに完全なスキーママイグレーションが適用された Postgres DB を生成している
    以前スタートアップで btrfs を使って即時ステージング DB を作るのを見たことがあり、こうした似たアイデアが何度も現れるのは興味深い
    このような 高速複製とテスト は Postgres と Sqlite の大きな利点で、Clickhouse や MySQL でも可能になってほしい

  • 最近の PostgreSQL は、ほぼあらゆる SQL の用途をカバーする万能 DB になったように見える
    しかも 無料
    もう他の SQL DB を使う理由があるのだろうかと思う

    • Postgres は素晴らしいが、MySQL はマスター・マスター複製がより簡単で、MongoDB は地理分散やシャーディングが容易だ
      Clickhouse は分析用途でははるかに高速で、Cassandra のような DB は書き込み中心のワークロードに向いている
      つまり、各 DB には今でもそれぞれ強みがある
    • 「何でもうまくやる」という表現は誇張だ
      データが増えると 性能低下マイグレーションの問題 が起きる
      自分の場合、標準のパーティショニング性能が低くて、自前でカスタムパーティションを実装しなければならなかった
    • Postgres は今でも MVCC の実装方式(copy-on-write)が非効率だ
      この選択が高負荷時にいくつもの悪影響を生む
    • 以前は MySQL/InnoDB のほうが更新中心のワークロードで優れていた
      Uberのブログ記事でも扱われていた話題だ
      それでもクラウド環境では Postgres を最も信頼している
    • Postgres にはまだ Vitess 級に成熟した代替がない
      そのため大規模な OLTPデプロイ では、今でも主に MySQL が使われている(例: YouTube, Uber)
  • 不変データ構造(HAMT) を使えば、ファイルシステムの種類に関係なく即時クローン可能な DB を作れる
    理論の話だと言っていたが、実際に実装してみた
    なぜこうした HAMTベースのDB がもっと増えないのか理解できない

    • 自分は ClickHouse の作者だが、ClickHouse も不変のデータパートを使ってテーブル複製をサポートしている
      関連ドキュメント
    • Datomic にもこうしたクローン機能が組み込まれているのか気になる。前から使ってみたいとは思っていたが、実際にアプリを作るにはまだ心の準備ができていない
  • Postgres v15 で WAL_LOG がデフォルトに変わっていたことを知らなかった
    並列 CI テスト環境では FILE_COPY 戦略に戻すほうが合理的だ
    以前のプロジェクト integresql に関連 issue を上げたことがある

  • ローカルで Postgres ベースのアプリをテストするためのシンプルな GUIツール pgtt を作ったことがある
    開発環境のセットアップをかなり単純化してくれる

    • README だけではよくわからないが、テンプレートを スナップショットのように 扱う構造なのか気になる
      SQL マイグレーションの繰り返し作業に役立ちそうだ
    • README に GUIのスクリーンショット があるとよいし、Dockerリンク が壊れている
  • ブログの他の記事も読んでみたが、全体的に素晴らしい
    特に Postgres の range 型 を初めて知った

    • range 型は 時間/日付範囲の重なり計算 のような場面で本当に便利だ
  • MariaDB にもこういう機能があるのか気になる
    テストごとに DB を初期状態へ戻すのが遅くて悩んでいる
    本番では MariaDB を使っているので、DB を変えるのは難しい
    Postgres のほうが良さそうには見える

    • 各テストを トランザクションセッション 内で実行し、最後にロールバックすれば素早く初期状態に戻せる
      この方法はかなり効率的だ
    • DB を再起動してもよいなら、LVMbtrfsスナップショット をファイルシステムレベルで使うのも方法だ
  • AWS でも類似機能を提供している
    Auroraクローンのドキュメント

    • Aurora のクローンはストレージレベルで copy-on-write として動作するが、それでも新しいクラスターをプロビジョニングする必要があり、約 10 分かかる
      統合テスト用途としては現実的ではない
    • Aurora は クラスタ単位 の複製で、ここで議論されているのは データベース単位 の複製だ