論理レプリケーションにおけるパブリケーションの行フィルター - PostgreSQL 15でコミットされた機能の先行紹介:技術者Blog
PostgreSQLインサイド

Peter Smith

Fujitsu Australia Software Technology
Senior Software Development Engineer

はじめに

Peter
通常、論理レプリケーションのパブリッシュとサブスクライブモデルを使用する場合、パブリッシュされたテーブルのすべてのデータ変更が適切なサブスクライバーにレプリケートされます。新しい行フィルター機能を使用すると、指定したフィルター式に一致する行データのみがレプリケートされるよう制限できるようになります。

目次

機能の概要

Peter
行フィルターは、CREATE PUBLICATION構文において、テーブルごとにオプションで指定します。行フィルター「WHERE句」を、行フィルターを適用するテーブルごとに追加します。各パブリケーションには、0個以上の行フィルターを持つことができます。

CREATE PUBLICATION構文の改良

Peter
次に、簡略化したCREATE PUBLICATION構文を示します。PostgreSQL 15で追加された新しい行フィルターのWHERE句を強調表示しています。

CREATE PUBLICATION <pub-name> FOR TABLE <table-list>
<table-list> ::= <table-list-item> [, <table-list>]
<table-list-item> ::= <table-name> [ WHERE (<row-filter-expression>) ]

行フィルター式

Peter
行フィルターのWHERE句では、基本的な関数と論理演算子を含む単純な式のみを使用できます。また、所属するテーブルのカラムのみを参照できます。パブリケーションがUPDATEまたはDELETEの操作をパブリッシュする場合、行フィルター式には、テーブルに「レプリカアイデンティティ(REPLICA IDENTITY)」が設定されているカラムを指定する必要があります。パブリケーションがINSERTの操作のみをパブリッシュする場合、行フィルター式にはテーブル内のどのカラムでも使用できます。

例1

CREATE PUBLICATION cheap_widgets
FOR TABLE widget WHERE (price < 1.99);

例2

CREATE PUBLICATION sales_people
FOR TABLE employees WHERE (role <> 'manager' AND dept = 'sales');

例3

CREATE PUBLICATION rate_usa    FOR TABLE exchange_rates WHERE (country = 'us');
CREATE PUBLICATION rate_uk     FOR TABLE exchange_rates WHERE (country = 'uk');
CREATE PUBLICATION rate_france FOR TABLE exchange_rates WHERE (country = 'fr');

行フィルターの適用

Peter
行フィルターが適用されるタイミングは、データの変更をパブリッシュするかどうかを決定する前です。なお、行フィルター式がNULLまたはfalseと評価された場合、その行はレプリケートされません。また、行フィルターにより、データを変更するコマンドは以下のように処理されます。

TRUNCATE TABLEコマンド

行フィルターは無視されます。

INSERTコマンド

INSERTとしてレプリケートされます。

DELETEコマンド

DELETEとしてレプリケートされます。

UPDATEコマンド

サブスクライバー側でレプリケートされたテーブルデータが、パブリッシャーで定義された行フィルター式に従う必要があるため、より複雑な動きになります。これを実現するために必要なアクションを決定するには、UPDATEが処理されるたびに、「古い」 行データと 「新しい」 行データの両方(つまり、UPDATEの前後)に対して行フィルター式を評価する必要があります。

  • 「古い」 行データは行フィルター式を満たしていないが(この行はサブスクライバーに存在しないものとします)、「新しい」 行データは行フィルター式を満たす場合、データの一貫性を保つため、 サブスクライバーに「新しい」 行を追加する必要があります。つまり、UPDATEはINSERTに変換されます(下表のA)。
  • 「古い」 行データは行フィルター式を満たすが(この行はすでにサブスクライバーに送信されていると断言します)、「新しい」 行データは行フィルター式を満たさない場合、データの一貫性を保つため、 サブスクライバーから「古い」 行を削除する必要があります。 つまり、UPDATEはDELETEに変換されます(下表のB)。
フィルターの一致有無 レプリケーション方法
古い行 新しい行
何もレプリケーションしません。
サブスクライバーに新しい行をINSERTします。(A)
サブスクライバーの古い行をDELETEします。(B)
サブスクライバーのUPDATEをレプリケートします。

複数の行フィルターの組み合わせ

Peter
1つのサブスクリプションが、複数のパブリケーションによってサブスクライブする場合があります。そのパブリケーションは、同じテーブルが異なる行フィルターのWHERE句でパブリッシュされたときです。この場合、これらの式はOR処理され、いずれかの式を満たす行がレプリケートされます。
これは、そのテーブルのサブスクライブされたパブリケーションの1つに行フィルターがない(全行が対象になる)場合、そのテーブルの他のすべての行フィルターが無視されることをも意味します。

複数の行フィルターの組み合わせ

テーブルの初期同期

Peter
ユーザーがCREATE SUBSCRIPTION構文でデフォルトの「copy_data=true」のパラメーターを選択すると、パブリケーションの行フィルターを満たす既存のデータのみがコピーされます。

psqlコマンドの拡張

Peter
この新機能の一部として、PostgreSQL 15のpsqlコマンドについても行フィルター式に関する有用な情報を提供するように拡張されました。
テーブルを表示するメタコマンド(¥d)では、そのテーブルがメンバーであるパブリケーションのWHERE句が表示されるようになりました。パブリケーションを一覧表示するメタコマンド(¥dRp+)では、任意のテーブルのWHERE句が表示されるようになりました。

例4

postgres=# CREATE TABLE data(id int, rgb text);
CREATE TABLE
postgres=# CREATE PUBLICATION pub_data_all FOR TABLE data;
CREATE PUBLICATION
postgres=# CREATE PUBLICATION pub_data_blue FOR TABLE data WHERE (rgb = 'B');
CREATE PUBLICATION
postgres=# CREATE PUBLICATION pub_data_red FOR TABLE data WHERE (rgb = 'R');
CREATE PUBLICATION
postgres=# ¥d data
                Table "public.data"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           |          | 
 rgb    | text    |           |          | 
Publications:
    "pub_data_all"
    "pub_data_blue" WHERE (rgb = 'B'::text)
    "pub_data_red" WHERE (rgb = 'R'::text)

postgres=# ¥dRp+
                          Publication pub_data_all
  Owner   | All tables | Inserts | Updates | Deletes | Truncates | Via root 
----------+------------+---------+---------+---------+-----------+----------
 postgres | f          | t       | t       | t       | t         | f
Tables:
    "public.data"

                         Publication pub_data_blue
  Owner   | All tables | Inserts | Updates | Deletes | Truncates | Via root 
----------+------------+---------+---------+---------+-----------+----------
 postgres | f          | t       | t       | t       | t         | f
Tables:
    "public.data" WHERE (rgb = 'B'::text)

                          Publication pub_data_red
  Owner   | All tables | Inserts | Updates | Deletes | Truncates | Via root 
----------+------------+---------+---------+---------+-----------+----------
 postgres | f          | t       | t       | t       | t         | f
Tables:
    "public.data" WHERE (rgb = 'R'::text)

postgres=#

効果

Peter
ユーザーが論理レプリケーションの行フィルター定義を利用することに、いくつかの理由があります。

例5:パフォーマンスの向上

大規模なデータテーブルの小さなサブセットのみをレプリケートすることで、ネットワークトラフィックを削減させる

CREATE PUBLICATION pub_data_2205
FOR TABLE bank_transactions WHERE (year = 2022 AND month = 'May');

例6:不要データの削減

データのノイズ(不要な部分)を低減させたり、不良データを除去したりする

CREATE PUBLICATION pub_data_good
FOR TABLE sensor WHERE (value IS NOT NULL AND value > 0);

例7:データの特定

サブスクライバーノードに関連するデータのみを提供する

CREATE PUBLICATION pub_data_new_york
FOR TABLE weather WHERE (state = 'NY');

例8:情報漏洩対策

機密情報を非表示(レプリケートしない)にすることで、セキュリティの一形態として動作させる

CREATE PUBLICATION pub_data_salary
FOR TABLE employees WHERE (role <> 'manager');

今後に向けて

Peter
行フィルターの追加は、PostgreSQL 15の論理レプリケーションの主要な機能です。この機能により、ユーザーのツールボックスにまた1つ便利な機能が増え、より洗練され、カスタマイズされた論理レプリケーション・ソリューションを作成できるようになります。今後も、富士通のOSSチームは、PostgreSQL論理レプリケーションの機能強化と機能追加を支援していきます。
PostgreSQL 15で追加された行フィルターに関連する機能として、「論理レプリケーションの列リスト」があります。これは、私の同僚が今後ブログで取り上げる予定です。

詳細情報

Peter
本ブログで解説した「パブリケーション行フィルター」についての詳細は、PostgreSQL文書またはGitHubに投稿したコミット情報をご覧ください。

行フィルターを記述するための情報や例について

新しい行フィルター「WHERE句」を記述するためのCREATE PUBLICATIONについて

「レプリカアイデンティティ」について

新しい行フィルター機能を追加するためのGitHubソースコードについて

2022年9月2日公開

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

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

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

お電話でのお問い合わせ

Webでのお問い合わせ

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

ページの先頭へ