バージョンごとのドキュメント一覧

29.4. 行フィルタ #

<title>Row Filters</title>

By default, all data from all published tables will be replicated to the appropriate subscribers. The replicated data can be reduced by using a <firstterm>row filter</firstterm>. A user might choose to use row filters for behavioral, security or performance reasons. If a published table sets a row filter, a row is replicated only if its data satisfies the row filter expression. This allows a set of tables to be partially replicated. The row filter is defined per table. Use a <literal>WHERE</literal> clause after the table name for each published table that requires data to be filtered out. The <literal>WHERE</literal> clause must be enclosed by parentheses. See <xref linkend="sql-createpublication"/> for details. デフォルトでは、すべてのパブリッシュされたテーブルのすべてのデータが適切なサブスクライバーにレプリケーションされます。 レプリケーションされたデータは、行フィルタを使用して削減できます。 ユーザは、動作、セキュリティまたはパフォーマンス上の理由で行フィルタの使用を選択できます。 パブリッシュされたテーブルに行フィルタが設定されている場合、行はそのデータが行フィルタ式を満たす場合にのみレプリケーションされます。 これにより、一連のテーブルを部分的にレプリケーションできます。 行フィルタはテーブルごとに定義されます。 データのフィルタ処理が必要なパブリッシュされたテーブルごとに、テーブル名の後にWHERE句を使用します。 WHERE句はカッコで囲む必要があります。 詳細はCREATE PUBLICATIONを参照してください。

29.4.1. 行フィルタルール #

<title>Row Filter Rules</title>

Row filters are applied <emphasis>before</emphasis> publishing the changes. If the row filter evaluates to <literal>false</literal> or <literal>NULL</literal> then the row is not replicated. The <literal>WHERE</literal> clause expression is evaluated with the same role used for the replication connection (i.e. the role specified in the <link linkend="sql-createsubscription-params-connection"><literal>CONNECTION</literal></link> clause of the <xref linkend="sql-createsubscription"/>). Row filters have no effect for <command>TRUNCATE</command> command. 行フィルタは、変更を発行する前に適用されます。 行フィルタがfalseまたはNULLと評価される場合、行はレプリケーションされません。 WHERE句の式は、レプリケーション接続に使用されるロールと同じロール(CREATE SUBSCRIPTIONCONNECTION句で指定されたロール)で評価されます。 TRUNCATEコマンドに対しては、行フィルタは無効です。

29.4.2. 式の制限 #

<title>Expression Restrictions</title>

The <literal>WHERE</literal> clause allows only simple expressions. It cannot contain user-defined functions, operators, types, and collations, system column references or non-immutable built-in functions. WHERE句では単純な式のみを使用できます。 ユーザ定義関数、演算子、型、照合、システム列参照、不変でない組み込み関数は使用できません。

If a publication publishes <command>UPDATE</command> or <command>DELETE</command> operations, the row filter <literal>WHERE</literal> clause must contain only columns that are covered by the replica identity (see <xref linkend="sql-altertable-replica-identity"/>). If a publication publishes only <command>INSERT</command> operations, the row filter <literal>WHERE</literal> clause can use any column. パブリケーションがUPDATEまたはDELETE操作をパブリッシュする場合、行フィルタWHERE句には、レプリカアイデンティティの対象となる列のみを含める必要があります(REPLICA IDENTITYを参照)。 パブリケーションがINSERT操作のみをパブリッシュする場合、行フィルタWHERE句は任意の列を使用できます。

29.4.3. UPDATE変換 #

<title>UPDATE Transformations</title>

Whenever an <command>UPDATE</command> is processed, the row filter expression is evaluated for both the old and new row (i.e. using the data before and after the update). If both evaluations are <literal>true</literal>, it replicates the <command>UPDATE</command> change. If both evaluations are <literal>false</literal>, it doesn't replicate the change. If only one of the old/new rows matches the row filter expression, the <command>UPDATE</command> is transformed to <command>INSERT</command> or <command>DELETE</command>, to avoid any data inconsistency. The row on the subscriber should reflect what is defined by the row filter expression on the publisher. UPDATEが処理されるたびに、行フィルタ式は古い行と新しい行の両方に対して評価されます(つまり、更新前後のデータを使用します)。 両方の評価がtrueの場合、UPDATE変更がレプリケーションされます。 両方の評価がfalseの場合、変更はレプリケーションされません。 古い行と新しい行のいずれか1つのみが行フィルタ式に一致する場合、データの不整合を回避するためにUPDATEINSERTまたはDELETEに変換されます。 サブスクライバーの行は、パブリッシャーの行フィルタ式で定義されている内容を反映する必要があります。

If the old row satisfies the row filter expression (it was sent to the subscriber) but the new row doesn't, then, from a data consistency perspective the old row should be removed from the subscriber. So the <command>UPDATE</command> is transformed into a <command>DELETE</command>. 古い行が行フィルタ式を満たしていて(サブスクライバーに送信された)、新しい行が満たさない場合、データの整合性の観点から、古い行はサブスクライバーから削除される必要があります。 したがって、UPDATEDELETEに変換されます。

If the old row doesn't satisfy the row filter expression (it wasn't sent to the subscriber) but the new row does, then, from a data consistency perspective the new row should be added to the subscriber. So the <command>UPDATE</command> is transformed into an <command>INSERT</command>. 古い行が行フィルタ式を満たさず(サブスクライバーに送信されなかった)、新しい行がそれを満たす場合は、データの整合性の観点から、新しい行をサブスクライバーに追加する必要があります。 したがって、UPDATEINSERTに変換されます。

<xref linkend="logical-replication-row-filter-transformations-summary"/> summarizes the applied transformations. 表 29.1は、適用された変換を要約します。

表29.1 UPDATE変換要約

<title><command>UPDATE</command> Transformation Summary</title>
古い行新しい行変換
一致せず一致せずレプリケーションしない
一致せず一致INSERT
一致一致せずDELETE
一致一致UPDATE

29.4.4. パーティション化テーブル #

<title>Partitioned Tables</title>

If the publication contains a partitioned table, the publication parameter <link linkend="sql-createpublication-params-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link> determines which row filter is used. If <literal>publish_via_partition_root</literal> is <literal>true</literal>, the <emphasis>root partitioned table's</emphasis> row filter is used. Otherwise, if <literal>publish_via_partition_root</literal> is <literal>false</literal> (default), each <emphasis>partition's</emphasis> row filter is used. パブリケーションにパーティション化テーブルが含まれている場合、パブリケーションパラメータpublish_via_partition_rootによって使用される行フィルタが決定されます。 publish_via_partition_roottrueの場合、ルートのパーティション化テーブルの行フィルタが使用されます。 それ以外の場合、publish_via_partition_rootfalse(デフォルト)の場合、パーティションの行フィルタがそれぞれ使用されます。

29.4.5. 初期データ同期 #

<title>Initial Data Synchronization</title>

If the subscription requires copying pre-existing table data and a publication contains <literal>WHERE</literal> clauses, only data that satisfies the row filter expressions is copied to the subscriber. サブスクリプションで既存のテーブル・データをコピーする必要があり、パブリケーションにWHERE句が含まれている場合、行フィルタ式を満たすデータのみがサブスクライバーにコピーされます。

If the subscription has several publications in which a table has been published with different <literal>WHERE</literal> clauses, rows that satisfy <emphasis>any</emphasis> of the expressions will be copied. See <xref linkend="logical-replication-row-filter-combining"/> for details. サブスクリプションに複数のパブリケーションがあり、テーブルが異なるWHERE句でパブリッシュされている場合は、式のanyを満たす行がコピーされます。 詳細は29.4.6を参照してください。

警告

Because initial data synchronization does not take into account the <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link> parameter when copying existing table data, some rows may be copied that would not be replicated using DML. Refer to <xref linkend="logical-replication-snapshot"/>, and see <xref linkend="logical-replication-subscription-examples"/> for examples. 初期データ同期では、既存のテーブルデータをコピーする際にpublishパラメータが考慮されないため、DMLを使用してレプリケーションされない行がコピーされる場合があります。 29.8.1および29.2.2の例を参照してください。

注記

If the subscriber is in a release prior to 15, copy pre-existing data doesn't use row filters even if they are defined in the publication. This is because old releases can only copy the entire table data. サブスクライバーが15より前のリリースにある場合、既存のデータのコピーでは、パブリケーションで定義されていても行フィルタは使用されません。 これは、古いリリースではテーブルデータ全体しかコピーできないためです。

29.4.6. 複数行フィルタの統合 #

<title>Combining Multiple Row Filters</title>

If the subscription has several publications in which the same table has been published with different row filters (for the same <link linkend="sql-createpublication-params-with-publish"><literal>publish</literal></link> operation), those expressions get ORed together, so that rows satisfying <emphasis>any</emphasis> of the expressions will be replicated. This means all the other row filters for the same table become redundant if: サブスクリプションに複数のパブリケーションがあり、その中で同じテーブルが異なる行フィルタを使用してパブリッシュされている場合(同じパブリッシュ操作の場合)、これらの式はOR結合され、式のいずれかを満たす行がレプリケーションされます。 これは、次の場合、同じテーブルの他のすべての行フィルタが冗長になることを意味します。

  • One of the publications has no row filter. パブリケーションの1つに行フィルタがない。

  • One of the publications was created using <link linkend="sql-createpublication-params-for-all-tables"><literal>FOR ALL TABLES</literal></link>. This clause does not allow row filters. パブリケーションの1つがFOR ALL TABLESを使用して作成された。 この句では行フィルタを使用できません。

  • One of the publications was created using <link linkend="sql-createpublication-params-for-tables-in-schema"><literal>FOR TABLES IN SCHEMA</literal></link> and the table belongs to the referred schema. This clause does not allow row filters. パブリケーションの1つがFOR TABLES IN SCHEMAを使用して作成され、テーブルは参照されたスキーマに属している。 この句では、行フィルタは使用できません。

29.4.7. 例 #

<title>Examples</title>

Create some tables to be used in the following examples. 次の例で使用するテーブルをいくつか作成します。

test_pub=# CREATE TABLE t1(a int, b int, c text, PRIMARY KEY(a,c));
CREATE TABLE
test_pub=# CREATE TABLE t2(d int, e int, f int, PRIMARY KEY(d));
CREATE TABLE
test_pub=# CREATE TABLE t3(g int, h int, i int, PRIMARY KEY(g));
CREATE TABLE

Create some publications. Publication <literal>p1</literal> has one table (<literal>t1</literal>) and that table has a row filter. Publication <literal>p2</literal> has two tables. Table <literal>t1</literal> has no row filter, and table <literal>t2</literal> has a row filter. Publication <literal>p3</literal> has two tables, and both of them have a row filter. いくつかのパブリケーションを作成します。 パブリケーションp1には1つのテーブルt1があり、そのテーブルには行フィルタがあります。 パブリケーションp2には2つのテーブルがあります。 テーブルt1には行フィルタがなく、テーブルt2には行フィルタがあります。 パブリケーションp3には2つのテーブルがあり、両方に行フィルタがあります。

test_pub=# CREATE PUBLICATION p1 FOR TABLE t1 WHERE (a > 5 AND c = 'NSW');
CREATE PUBLICATION
test_pub=# CREATE PUBLICATION p2 FOR TABLE t1, t2 WHERE (e = 99);
CREATE PUBLICATION
test_pub=# CREATE PUBLICATION p3 FOR TABLE t2 WHERE (d = 10), t3 WHERE (g = 10);
CREATE PUBLICATION

<command>psql</command> can be used to show the row filter expressions (if defined) for each publication. psqlを使用して、各パブリケーションの行フィルタ式(定義されている場)を表示することができます。

test_pub=# \dRp+
                               Publication p1
  Owner   | All tables | Inserts | Updates | Deletes | Truncates | Via root
----------+------------+---------+---------+---------+-----------+----------
 postgres | f          | t       | t       | t       | t         | f
Tables:
    "public.t1" WHERE ((a > 5) AND (c = 'NSW'::text))

                               Publication p2
  Owner   | All tables | Inserts | Updates | Deletes | Truncates | Via root
----------+------------+---------+---------+---------+-----------+----------
 postgres | f          | t       | t       | t       | t         | f
Tables:
    "public.t1"
    "public.t2" WHERE (e = 99)

                               Publication p3
  Owner   | All tables | Inserts | Updates | Deletes | Truncates | Via root
----------+------------+---------+---------+---------+-----------+----------
 postgres | f          | t       | t       | t       | t         | f
Tables:
    "public.t2" WHERE (d = 10)
    "public.t3" WHERE (g = 10)

<command>psql</command> can be used to show the row filter expressions (if defined) for each table. See that table <literal>t1</literal> is a member of two publications, but has a row filter only in <literal>p1</literal>. See that table <literal>t2</literal> is a member of two publications, and has a different row filter in each of them. psqlを使用して、各テーブルの行フィルタ式(定義されている場合)を表示できます。 テーブルt1は2つのパブリケーションのメンバですが、p1にのみ行フィルタがあります。 テーブルt2は2つのパブリケーションのメンバですが、それぞれに異なる行フィルタがあります。

test_pub=# \d t1
                 Table "public.t1"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 a      | integer |           | not null |
 b      | integer |           |          |
 c      | text    |           | not null |
Indexes:
    "t1_pkey" PRIMARY KEY, btree (a, c)
Publications:
    "p1" WHERE ((a > 5) AND (c = 'NSW'::text))
    "p2"

test_pub=# \d t2
                 Table "public.t2"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 d      | integer |           | not null |
 e      | integer |           |          |
 f      | integer |           |          |
Indexes:
    "t2_pkey" PRIMARY KEY, btree (d)
Publications:
    "p2" WHERE (e = 99)
    "p3" WHERE (d = 10)

test_pub=# \d t3
                 Table "public.t3"
 Column |  Type   | Collation | Nullable | Default
--------+---------+-----------+----------+---------
 g      | integer |           | not null |
 h      | integer |           |          |
 i      | integer |           |          |
Indexes:
    "t3_pkey" PRIMARY KEY, btree (g)
Publications:
    "p3" WHERE (g = 10)

On the subscriber node, create a table <literal>t1</literal> with the same definition as the one on the publisher, and also create the subscription <literal>s1</literal> that subscribes to the publication <literal>p1</literal>. サブスクライバーノードで、パブリッシャーと同じ定義のテーブルt1を作成し、パブリケーションp1をサブスクライブするサブスクリプションs1も作成します。

test_sub=# CREATE TABLE t1(a int, b int, c text, PRIMARY KEY(a,c));
CREATE TABLE
test_sub=# CREATE SUBSCRIPTION s1
test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=s1'
test_sub-# PUBLICATION p1;
CREATE SUBSCRIPTION

Insert some rows. Only the rows satisfying the <literal>t1 WHERE</literal> clause of publication <literal>p1</literal> are replicated. いくつかの行を挿入します。 パブリケーションp1t1 WHERE句を満たす行のみがレプリケーションされます。

test_pub=# INSERT INTO t1 VALUES (2, 102, 'NSW');
INSERT 0 1
test_pub=# INSERT INTO t1 VALUES (3, 103, 'QLD');
INSERT 0 1
test_pub=# INSERT INTO t1 VALUES (4, 104, 'VIC');
INSERT 0 1
test_pub=# INSERT INTO t1 VALUES (5, 105, 'ACT');
INSERT 0 1
test_pub=# INSERT INTO t1 VALUES (6, 106, 'NSW');
INSERT 0 1
test_pub=# INSERT INTO t1 VALUES (7, 107, 'NT');
INSERT 0 1
test_pub=# INSERT INTO t1 VALUES (8, 108, 'QLD');
INSERT 0 1
test_pub=# INSERT INTO t1 VALUES (9, 109, 'NSW');
INSERT 0 1

test_pub=# SELECT * FROM t1;
 a |  b  |  c
---+-----+-----
 2 | 102 | NSW
 3 | 103 | QLD
 4 | 104 | VIC
 5 | 105 | ACT
 6 | 106 | NSW
 7 | 107 | NT
 8 | 108 | QLD
 9 | 109 | NSW
(8 rows)

test_sub=# SELECT * FROM t1;
 a |  b  |  c
---+-----+-----
 6 | 106 | NSW
 9 | 109 | NSW
(2 rows)

Update some data, where the old and new row values both satisfy the <literal>t1 WHERE</literal> clause of publication <literal>p1</literal>. The <command>UPDATE</command> replicates the change as normal. 古い行の値と新しい行の値の両方がパブリケーションp1t1 WHERE句を満たすデータを更新します。 UPDATEは、通常のように変更をレプリケーションします。

test_pub=# UPDATE t1 SET b = 999 WHERE a = 6;
UPDATE 1

test_pub=# SELECT * FROM t1;
 a |  b  |  c
---+-----+-----
 2 | 102 | NSW
 3 | 103 | QLD
 4 | 104 | VIC
 5 | 105 | ACT
 7 | 107 | NT
 8 | 108 | QLD
 9 | 109 | NSW
 6 | 999 | NSW
(8 rows)

test_sub=# SELECT * FROM t1;
 a |  b  |  c
---+-----+-----
 9 | 109 | NSW
 6 | 999 | NSW
(2 rows)

Update some data, where the old row values did not satisfy the <literal>t1 WHERE</literal> clause of publication <literal>p1</literal>, but the new row values do satisfy it. The <command>UPDATE</command> is transformed into an <command>INSERT</command> and the change is replicated. See the new row on the subscriber. 古い行の値はパブリケーションp1t1 WHERE句を満たしていませんが、新しい行の値はこの句を満たしているデータを更新します。 UPDATEINSERTに変換され、変更がレプリケーションされます。 サブスクライバーの新しい行を参照してください。

test_pub=# UPDATE t1 SET a = 555 WHERE a = 2;
UPDATE 1

test_pub=# SELECT * FROM t1;
  a  |  b  |  c
-----+-----+-----
   3 | 103 | QLD
   4 | 104 | VIC
   5 | 105 | ACT
   7 | 107 | NT
   8 | 108 | QLD
   9 | 109 | NSW
   6 | 999 | NSW
 555 | 102 | NSW
(8 rows)

test_sub=# SELECT * FROM t1;
  a  |  b  |  c
-----+-----+-----
   9 | 109 | NSW
   6 | 999 | NSW
 555 | 102 | NSW
(3 rows)

Update some data, where the old row values satisfied the <literal>t1 WHERE</literal> clause of publication <literal>p1</literal>, but the new row values do not satisfy it. The <command>UPDATE</command> is transformed into a <command>DELETE</command> and the change is replicated. See that the row is removed from the subscriber. 古い行の値がパブリケーションp1t1 WHERE句を満たしていますが、新しい行の値がこの句を満たしていないデータを更新します。 UPDATEDELETEに変換され、変更がレプリケーションされます。 行がサブスクライバーから削除されていることを確認します。

test_pub=# UPDATE t1 SET c = 'VIC' WHERE a = 9;
UPDATE 1

test_pub=# SELECT * FROM t1;
  a  |  b  |  c
-----+-----+-----
   3 | 103 | QLD
   4 | 104 | VIC
   5 | 105 | ACT
   7 | 107 | NT
   8 | 108 | QLD
   6 | 999 | NSW
 555 | 102 | NSW
   9 | 109 | VIC
(8 rows)

test_sub=# SELECT * FROM t1;
  a  |  b  |  c
-----+-----+-----
   6 | 999 | NSW
 555 | 102 | NSW
(2 rows)

The following examples show how the publication parameter <link linkend="sql-createpublication-params-with-publish-via-partition-root"><literal>publish_via_partition_root</literal></link> determines whether the row filter of the parent or child table will be used in the case of partitioned tables. 次の例は、パブリケーションパラメータpublish_via_partition_rootによって、親テーブルまたは子テーブルの行フィルタがパーティション化されたテーブルで使用されるかどうかがどのように決定されるかを示しています。

Create a partitioned table on the publisher. パブリッシャーでパーティション化テーブルを作成します。

test_pub=# CREATE TABLE parent(a int PRIMARY KEY) PARTITION BY RANGE(a);
CREATE TABLE
test_pub=# CREATE TABLE child PARTITION OF parent DEFAULT;
CREATE TABLE

Create the same tables on the subscriber. サブスクライバー上に同じテーブルを作成します。

test_sub=# CREATE TABLE parent(a int PRIMARY KEY) PARTITION BY RANGE(a);
CREATE TABLE
test_sub=# CREATE TABLE child PARTITION OF parent DEFAULT;
CREATE TABLE

Create a publication <literal>p4</literal>, and then subscribe to it. The publication parameter <literal>publish_via_partition_root</literal> is set as true. There are row filters defined on both the partitioned table (<literal>parent</literal>), and on the partition (<literal>child</literal>). パブリケーションp4を作成し、サブスクライブします。 パブリケーションパラメータpublish_via_partition_rootはtrueに設定されています。 行フィルタは、パーティション化テーブル(parent)とパーティション(child)の両方に定義されています。

test_pub=# CREATE PUBLICATION p4 FOR TABLE parent WHERE (a < 5), child WHERE (a >= 5)
test_pub-# WITH (publish_via_partition_root=true);
CREATE PUBLICATION

test_sub=# CREATE SUBSCRIPTION s4
test_sub-# CONNECTION 'host=localhost dbname=test_pub application_name=s4'
test_sub-# PUBLICATION p4;
CREATE SUBSCRIPTION

Insert some values directly into the <literal>parent</literal> and <literal>child</literal> tables. They replicate using the row filter of <literal>parent</literal> (because <literal>publish_via_partition_root</literal> is true). 一部の値をおよびテーブルに直接挿入します。 これらの値は、の行フィルタを使用してレプリケーションされます(publish_via_partition_rootがtrueであるため)。

test_pub=# INSERT INTO parent VALUES (2), (4), (6);
INSERT 0 3
test_pub=# INSERT INTO child VALUES (3), (5), (7);
INSERT 0 3

test_pub=# SELECT * FROM parent ORDER BY a;
 a
---
 2
 3
 4
 5
 6
 7
(6 rows)

test_sub=# SELECT * FROM parent ORDER BY a;
 a
---
 2
 3
 4
(3 rows)

Repeat the same test, but with a different value for <literal>publish_via_partition_root</literal>. The publication parameter <literal>publish_via_partition_root</literal> is set as false. A row filter is defined on the partition (<literal>child</literal>). 同じテストを、異なる値publish_via_partition_rootで繰り返します。 パブリケーションパラメータpublish_via_partition_rootは偽に設定されています。 行フィルタがパーティション(child)に定義されています。

test_pub=# DROP PUBLICATION p4;
DROP PUBLICATION
test_pub=# CREATE PUBLICATION p4 FOR TABLE parent, child WHERE (a >= 5)
test_pub-# WITH (publish_via_partition_root=false);
CREATE PUBLICATION

test_sub=# ALTER SUBSCRIPTION s4 REFRESH PUBLICATION;
ALTER SUBSCRIPTION

Do the inserts on the publisher same as before. They replicate using the row filter of <literal>child</literal> (because <literal>publish_via_partition_root</literal> is false). パブリッシャーで挿入を前と同じように実行します。 これらはchildの行フィルタを使用してレプリケーションされます(publish_via_partition_rootがfalseであるため)。

test_pub=# TRUNCATE parent;
TRUNCATE TABLE
test_pub=# INSERT INTO parent VALUES (2), (4), (6);
INSERT 0 3
test_pub=# INSERT INTO child VALUES (3), (5), (7);
INSERT 0 3

test_pub=# SELECT * FROM parent ORDER BY a;
 a
---
 2
 3
 4
 5
 6
 7
(6 rows)

test_sub=# SELECT * FROM child ORDER BY a;
 a
---
 5
 6
 7
(3 rows)