論理レプリケーションにおけるパブリケーションの行フィルター - 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について
「レプリカアイデンティティ」について
- https://www.postgresql.org/docs/current/logical-replication-publication.html(PostgreSQLオフィシャルのページへ)
- https://www.postgresql.org/docs/current/sql-altertable.html#SQL-ALTERTABLE-REPLICA-IDENTITY(PostgreSQLオフィシャルのページへ)
新しい行フィルター機能を追加するためのGitHubソースコードについて
2022年9月2日公開
富士通のソフトウェア公式チャンネル(YouTube)
-
- 富士通のミドルウェア製品のご紹介や各種イベント・セミナーの講演内容、デモンストレーションなどの動画をご覧いただけます。
- 富士通のミドルウェア製品のご紹介や各種イベント・セミナーの講演内容、デモンストレーションなどの動画をご覧いただけます。
PostgreSQLについてより深く知る
PostgreSQLに興味をお持ちのお客様はこちらのコンテンツもお勧めです。ぜひご覧ください。
本コンテンツに関するお問い合わせ
お電話でのお問い合わせ
-
富士通コンタクトライン(総合窓口)
0120-933-200受付時間:9時~12時および13時~17時30分(土曜日・日曜日・祝日・当社指定の休業日を除く)