PostgreSQL 15とその後:技術者Blog
PostgreSQLインサイド

Amit Kapila

FUJITSU Limited
Software Products Business Unit Data Management Division
Senior Director

はじめに

PostgreSQLの伝統を引き継ぎ、PostgreSQL 15ではいくつかの改善を提供し、さらにいくつかのユースケースにおいてコーディングを簡素化する非常に便利な新しいコマンドも追加しました。これらについて見ていきましょう。

目次

論理レプリケーションの改善

このバージョンでは、論理レプリケーションにいくつかの改善が加えられています。

  • 組み込み論理レプリケーションにおいてプリペアドトランザクションをサポートします。
    プリペアドトランザクションをレプリケーションできるようにするには、サブスクリプションの作成時に two_phase = true オプションを指定します。

    CREATE PUBLICATION mypub FOR ALL TABLES;
    CREATE SUBSCRIPTION mysub CONNECTION 'dbname=postgres'
        PUBLICATION  mypub WITH (two_phase = true);
    

    この機能により、コミット時にすべてのトランザクションデータを送信するのではなく、プリペア時にデータの送信を開始します。プリペアとコミットの間には長い時間差が生じる可能性があるため、この機能によりデータをレプリケートするときの遅延が軽減されます。
    また、これにより、コンフリクトのない論理レプリケーションを構築するための基盤が提供されたことになります。これは、サブスクライバーにトランザクションを適用している際、プリペア時にコンフリクトが検出された場合、パブリッシャー側でもプリペアをロールバックできるためです。なお、PostgreSQLではデフォルトでこのようなことは実行できませんので、アプリケーション側で注意して変更する必要があります。これについては、私のブログ記事「PostgreSQL 15での論理レプリケーションの改善」で詳しく書いています。

  • パブリケーションは、スキーマ内のすべてのテーブルをパブリッシュできるようになりました。
    PostgreSQL 14以前は、ユーザーがスキーマ内のすべてのテーブルをパブリッシュする場合、各テーブルを個別に指定する必要がありました。しかし、この新しい句を使用すると、スキーマ内のすべてのテーブルを個別に指定することなくレプリケートできます。また、ユーザーが個々のテーブルを指定できる既存の構文と併せて使用することもできます。

    CREATE PUBLICATION mypub FOR TABLES IN SCHEMA mysch;
    CREATE PUBLICATION mypub FOR TABLE mytab, TABLES IN SCHEMA mysch;

    記載されたスキーマに後から追加されたテーブルもレプリケートされます。
    詳細については、当社のブログ記事「スキーマ内のテーブルを対象とした論理レプリケーション」で紹介しています。

  • WHERE句を使用してパブリケーションの内容をフィルタリング(除外)できるようになりました。

    CREATE PUBLICATION mypub FOR TABLE mytab WHERE (c1 > 10);

    これにより、ノード間でデータを分散したり、選択したデータのみを送信することで性能を向上させたりすることができます。現在、WHERE句では単純な式しか使用できません。ユーザーが定義した関数・演算子・型・照合順序、システム列参照、または非immutable関数を含めることはできません(ただし、これらの制限は将来のリリースで解除される可能性があります)。
    パブリケーションがUPDATEまたはDELETE操作をパブリッシュする場合、行フィルターのWHERE句にはレプリカアイデンティティの対象となる列のみを含める必要があります。INSERT操作のみをパブリッシュする場合、WHERE句には任意の列を指定できます。詳細については、当社のブログ記事「論理レプリケーションにおけるパブリケーションの行フィルター」をご覧ください。

  • パブリケーションでは、特定の列のみをパブリッシュできるようになりました。
    この機能は、行フィルターと似ていますが、パブリケーションを列のサブセットに制限できる点が異なります。

    CREATE PUBLICATION mypub FOR TABLE mytab (c1, c2);

    列リストは、動作上または性能上の理由に基づいて作成でき、単純な列参照のみを含むことができます。パブリケーションが FOR TABLES IN SCHEMA もパブリッシュする場合、列リストを指定できません(ただし、この制限は将来的に解除される可能性があります)。
    パブリケーションがUPDATEまたはDELETE操作を発行する場合、列リストにはテーブルのレプリカアイデンティティ列が含まれている必要があります。INSERT操作のみをパブリッシュする場合、列リストではレプリカアイデンティティ列を省略できます。
    詳細については、当社のブログ記事「論理レプリケーションにおける列リスト」をご覧ください。

  • 論理レプリケーションは、サブスクリプションの所有者として実行できるようになりました。
    PostgreSQL 14以前は、レプリケーションはスーパーユーザーとして実行する必要がありました。PostgreSQL 15では、スーパーユーザー、BYPASSRLS属性を持つロール、およびテーブル所有者のみが、行単位のセキュリティポリシーが有効なテーブルにレプリケーションを実行できます。

  • PostgreSQL 14以前は、コンフリクトするデータを手動で削除するか、pg_replication_origin_advance関数を使用してトランザクションをスキップすることでコンフリクトを解決できましたが、どちらの方法もユーザーにとって非常に難しいものでした。
    PostgreSQL 15では、コンフリクトするトランザクションのLSNを指定してユーザーがスキップできるようにすることで、より簡単な方法を提供しました。

    ALTER SUBSCRIPTION mysub SKIP (lsn = 0/14C0378)

    ユーザーが指定する必要がある失敗したトランザクションの LSN は、サーバーログで確認できます。
    詳細については、当社のブログ記事「論理レプリケーションにおけるコンフリクトの対処方法(ALTER SUBSCRIPTION … SKIPコマンド)」をご覧ください。

  • ユーザーは、コンフリクト時に自動的にレプリケーションを無効にするパラメーターを設定できます。例えば、主キー違反や他の制約違反などの自動的に解決されない場合など、人手を介さなければ再試行が成功しない可能性があるシナリオに役立ちます。
  • 新しいシステム ビュー pg_stat_subscription_statsは、論理レプリケーションの変更適用中または初期テーブル同期中に発生したエラーに関する統計を表示します。

MERGEコマンド

PostgreSQLコミュニティーは数年にわたりMERGE機能に取り組んできました。そして、PostgreSQL 15では、このコマンドが実装され、INSERT、UPDATE、DELETEの操作をすべて1つのトランザクションで処理できるようになりました。
次の例では、テーブルが一致し、指定された条件を満たすかどうかによって、MERGEコマンドのターゲットテーブルに対して挿入、更新、削除を行います。

MERGE INTO TargetProducts Target
USING SourceProducts Source
ON Source.ProductID = Target.ProductID
WHEN NOT MATCHED AND Source.ProductId IS NOT NULL THEN
  INSERT VALUES (Source.ProductID, Source.ProductName, Source.Price)
WHEN MATCHED AND Target.ProductName IN ('Table', 'Desk') THEN
  UPDATE SET ProductName = Source.ProductName, Price = Source.Price
WHEN MATCHED THEN
  DELETE;

MERGEコマンドを使用しない場合、上記の例では様々なif-else条件を持つ手続き言語を使ったプロシージャやSQL関数が必要となり、実行時間も長くなってしまいます。

結合によって、MERGEコマンドのターゲットテーブルの行ごとに最大1つの変更候補行が生成されるようにしないと、"MERGE command cannot affect row a second time "というエラーが発生します。各変更候補行に対して、最初にtrueと評価された句が実行されます。
一般的なケースとして、データウェアハウスでSCD(Slowly Changing Dimensions)を維持しようとする場合があります。このような場合、次のことが必要になります。

  • データウェアハウスに新しいレコードを挿入する。
  • ソースに存在しないレコードをデータウェアハウスから削除する。
  • ソースで更新されたデータウェアハウスの値を更新する。

Timothy Stewardは、このコマンドについて当社のブログ記事「The PostgreSQL MERGE command – a useful tool to make your code more efficient」に詳しく書いています。

ベースバックアップ

これはPostgreSQLでは昔からある機能で、リリースを重ねるごとに進化し、PostgreSQL 15でも改善されています。pg_basebackupコマンドでは、バックアップの場所を指定できるようになり、様々な圧縮オプションもサポートされました。
バックアップの場所は、-t targetまたは--target=targetオプションを使用して指定します。targetオプションには、client(デフォルト値、コマンドを実行しているマシンにバックアップを送信)、server(サーバーにバックアップを保存)、またはblackhole(内容を破棄し、テストとデバッグ目的でのみ使用)を指定できます。ただし、このオプションは、デフォルトのWALストリーミングオプション -X streamと一緒に使用できないことに注意してください。
バックアップに関するよくある不満の1つに、バックアップのサイズが大きいと時間がかかるというものがありました。そこで、PostgreSQL 15では、サーバー側の圧縮とクライアント側の圧縮が導入されました。バックアップは、サーバー側でもクライアント側でも、gzip、LZ4、Zstandardの圧縮オプションで圧縮できます(gzipによるクライアント側の圧縮はPostgreSQL 14以前にも可能であったことに注意してください)。これらの機能により、より高速でより容量の少ないバックアップが可能になります。

ソート性能の改善

メモリーとディスクの両方でソートするために導入された重要な性能改善についても説明します。

インメモリーソート

インメモリーソートの性能が改善しただけでなく、メモリー消費量を抑えるように最適化されました。

  • 単一列ソートの性能が25%以上改善しました。これは、結果に単一列も含まれる場合にのみ適用されます。
    例えば、この改善は SELECT col1 from mytab ORDER BY col1; には適用されますが、SELECT col1, col2 from mytab ORDER BY col1; には適用されません。

  • generationメモリーコンテキストを使用することで、メモリー使用量が削減されました。
    PostgreSQL 14以前では、要求を次の2の累乗に丸めるメモリー割り当て機構を使用していました。性能改善はタプルのサイズに依存しますが、最大で40%程度の改善が見られます。

  • 関数呼び出しのオーバーヘッドは、一般的なデータ型に特化したソートルーチンを追加することで削減されました。
    その結果、5%程度の改善が見られました。

work_memを超えるソート

work_mem(ソートなどに利用されるメモリーサイズ) を超えるソートの性能も、以前より多くの出力ストリームを使用するバッチソートアルゴリズムに切り替えることによって改善されました。改善は work_mem に依存し、その値が小さいほど改善は大きくなり、40% 程度改善しました。PostgreSQLコミュニティーの同僚の1人がこれらの性能改善について、こちらに素晴らしいブログ記事を書いています。

PostgreSQL 16とその後

最後に、PostgreSQLコミュニティーで議論されている機能で、PostgreSQL 16またはそれ以降のバージョンに含まれる可能性のある機能を列挙したいと思います(ただし、これらの機能が実際に追加される保証はないことに注意してください)。これは、私がPostgreSQLコミュニティーでの議論を観察した結果に基づく単なる要約であり、私やコミュニティーはこれらの機能が実装されることを保証するものではありません。

  • 論理レプリケーションの様々な改善

    • 起点に基づいてフィルタリングすることにより、同一テーブルのレプリケーションを許可
      現在、同一テーブルの双方向レプリケーションは無限ループに陥りますが、起点に基づくフィルタリングによる同一テーブルレプリケーションを許可することで、無限ループは発生しなくなります。
    • 並列適用
    • シーケンスのレプリケーション
    • スタンバイからの論理レプリケーション
    • DDLコマンドのレプリケーション
    • タイムディレイレプリケーション
    • パブリッシャー側でレプリカアイデンティティにfullを指定された場合のサブスクライバー側でのインデックスの使用
    • ラージオブジェクト(LOB)のような他のオブジェクトのレプリケーション
    • など
  • スーパーユーザー権限を必要とするコマンドの数の削減
  • 標準規格への準拠性を向上させるための SQL/JSON の改善
  • 透過的な列の暗号化 - クライアント内の特定の列の自動的で透過的な暗号化と復号化
  • ビルドインフラストラクチャーをMesonビルドシステムに置き換え(開発者向けの機能)
  • 非同期I/O - データのプリフェッチを可能にし、システムの性能を改善
  • ダイレクトI/O - OS キャッシュをバイパスすることによる性能改善(場合による)
  • ハッシュインデックスのさまざまな改善 - 一意のインデックスと複数列のインデックスを許可
  • パフォーマンスデータ構造の使用、relfrozenxidの早期化、WAL量の削減によるバキューム技術の改善
  • パーティショニング技術の改善
  • 統計/監視の改善
  • 64ビットのトランザクションID(XID)- 凍結を回避し、自動バキュームの必要性を削減
  • TDE(透過的データ暗号化) - 多くの組織のセキュリティ コンプライアンスを満たすのに役立つ
  • マテリアライズドビューの増分メンテナンス

PostgreSQLの進化

今後のリリースに向けては、まだまだいろいろな議論がおこなわれていますが、私は上記について注目しています。

2023年3月28日公開

オンデマンド(動画)セミナー

    • PostgreSQLに関連するセミナー動画を公開中。いつでもセミナーをご覧いただけます。
      • 【事例解説】運送業務改革をもたらす次世代の運送業界向けDXプラットフォームの構築
      • ハイブリッドクラウドに最適なOSSベースのデータベースご紹介

本コンテンツに関するお問い合わせ

お電話でのお問い合わせ

Webでのお問い合わせ

当社はセキュリティ保護の観点からSSL技術を使用しております。

ページの先頭へ