【PostgreSQL 11】外部テーブル (postgres_fdw) を利用したパーティションテーブルを作成してみた (その2)

こんにちは。サイオステクノロジー OSS サポート担当 Y です。

今回は、PostgreSQL 11 にて postgres_fdw (外部テーブル) を利用したパーティションテーブルと、ローカルで作成した (外部テーブルを利用せず、同一サーバ上で作成した) パーティションテーブルの動作を検証してみました。(※以下の内容は CentOS 7.6/PostgreSQL 10.6/PostgreSQL 11.1 にて検証しています。)

■はじめに

前回の記事では、PostgreSQL 11 にて postgres_fdw (外部テーブル) を利用したパーティションテーブルの作成と、親テーブルからのデータの INSERT を検証してみました。

今回は、postgres_fdw (外部テーブル) を利用したパーティションテーブルと、ローカルで作成した (外部テーブルを利用せず、同一サーバ上で作成した) パーティションテーブルで UPDATE を実行した際の動作の違いについて検証してみました。

■環境構成

それではさっそく、検証してみます。

今回は以下の様な構成の 2つのパーティションテーブル (RANGE パーティション) を作成します。(外部テーブルを利用したパーティションテーブルの作成については、前回の記事を参照して下さい。)

■ローカルでのパーティションテーブル作成

外部テーブルを利用したパーティションテーブルは前回の記事で作成したものをそのまま利用するため、今回はローカル (同一サーバ上) でのパーティションテーブルを追加で作成します。

以下の様に、親テーブル/子テーブルを作成します。

これで、ローカルでのパーティションテーブルの作成は完了です。

■データの INSERT

さて、現在検証用のサーバ (PostgreSQL 11) 上には、前述した方法で作成したパーティションテーブル (ローカルに作成) と、前回作成したパーティションテーブル (外部テーブルを利用) が存在しています。(基本的に、テーブルの定義は同じです。)

これらのテーブルに対して、それぞれテスト用のデータを INSERT します。

上記の様に INSERT/SELECT に関しては、どちらのパーティションテーブルでも問題なく実施することができました。

次に、パーティションキー以外のカラム (data) の値を UPDATE してみます。

パーティションキー以外のカラム (data) の更新も、問題無く実行することができました。

今度は、パーティションキー (key) の値を更新してみます。(先に結論を言ってしまうと、このパーティションキーの値の更新時の動作に一部違いがあります。)

まずは、更新後のパーティションキーの値が、各子テーブルの条件の範囲内 (*_hoge_1 の場合 1 =< key < 4) に収まる様な値に更新してみます。

更新後のパーティションキーの値が、各子テーブルの条件の範囲内 (*_hoge_1 の場合 1 =< key < 4) に収まる様な UPDATE は、どちらのパーティションテーブルでも問題なく実行することができました。

次に、更新後のパーティションキーの値が、異なる子テーブルの条件に合致する値になる様な更新を実行してみます。

最初に、外部テーブルを利用したパーティションテーブルにて、*_hoge_2 に格納されている key = 6 のレコードの key の値を “7” (*_hoge_3 の条件に合致する値) に更新します。

すると、key の値の UPDATE 自体は正常に実行されましたが、子テーブル間でのレコードの移動は行われず、子テーブル foreign_hoge_2 の中に条件 (4 <= key < 7) に合致しないレコード (key = 7) が格納されている状態になりました。

次に、ローカルのパーティションテーブル (外部テーブルを利用していないパーティションテーブル) にて、同じ様に *_hoge_2 に格納されている key = 6 のレコードの key の値を “7” (*_hoge_3 の条件に合致する値) に更新してみます。

すると今度は、子テーブル間でレコードが移動し、子テーブル local_hoge_2 の中から key = 6 だったレコード (data = ‘8a896920b5e331768cc17761eb49ab8d’ のレコード) が消え、local_hoge_3 に UPDATE 後の key = 7 のレコード (data = ‘8a896920b5e331768cc17761eb49ab8d’ のレコード) が格納されている状態になりました。

上記の様にパーティションキーの値を UPDATE した場合、ローカルのパーティションテーブルであれば、条件に合致する子テーブルに自動的にレコードを移動してくれます。

しかし、外部テーブルを利用したパーティションテーブルの場合、条件に合致する子テーブルへのレコードの移動は実施されません。

現時点 (PostgreSQL 11) における外部テーブルを利用したパーティションテーブルには、上記の様な制約があるようです。

私の個人的な見解ですが、外部テーブルを利用したパーティションテーブルの場合、複数ノードに跨る様なトランザクションを管理する (複数ノード間で原始性等を担保する) ための、2層 COMMIT のような仕組みがまだ実装されていないため、このような動作になっているのではないかと推測しています。

■おまけ

ちなみに、PostgreSQL 10 の場合はローカルのパーティションテーブルであっても、更新後のパーティションキーの値が、異なる子テーブルの条件に合致する様な更新を実行しようとすると、以下の様にエラーになってしまいます。

上記の通り、ローカルのパーティションテーブルにおいて、パーティションキーを更新した際の子テーブル間のレコードの移動は、PostgreSQL 11 から実装されている機能 (PostgreSQL 11 で強化された機能) になっています。

■最後に

今回は、PostgreSQL 11 にて外部テーブルを利用したパーティションテーブルと、ローカルで作成した (外部テーブルを利用せず、同一サーバ上で作成した) パーティションテーブルの動作を違いを検証してみました。

前述した通り、ローカルのパーティションテーブルにおけるパーティションキー更新時の子テーブル間のレコードの移動は、PostgreSQL 11 で実装 (強化) された機能となっており、バージョンが上がる毎に、少しずつ宣言的パーティショニングの機能が強化されています。

宣言的パーティショニングはユーザの期待も高く、注目されている機能であるため、今後のバージョン (PostgreSQL 12 以降) での更なる機能強化にも期待できるのではないでしょうか。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメント投稿

メールアドレスは表示されません。


*