【PostgreSQL 11 新機能】パーティションキーを UPDATE した際の動作を検証してみた

◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
【3/22開催】テックブログを書こう!アウトプットのススメ
1年で100本ブログを出した新米エンジニアがPV数が伸びなくてもTech Blogを書き続ける理由とは?
https://tech-lab.connpass.com/event/312805/

【4/18開催】VSCode Dev Containersで楽々開発環境構築祭り〜Python/Reactなどなど〜
Visual Studio Codeの拡張機能であるDev Containersを使ってReactとかPythonとかSpring Bootとかの開発環境をラクチンで構築する方法を紹介するイベントです。
https://tech-lab.connpass.com/event/311864/

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

今回は PostgreSQL 11 (現時点ではまだ beta 版) にて強化された “パーティションキーを UPDATE した際の動作” を検証してみました。(※以下の内容は CentOS 7.5/PostgreSQL 10.5/PostgreSQL 11beta3 にて検証しています。)

■はじめに

昨年リリースされた PostgreSQL 10 の新機能である Declarative Partitioning では、一度特定の子テーブルに格納されたレコードの “パーティションキー” の値を、異なる子テーブルの条件に合致する値に更新しようとすると ERROR になり、子テーブル間でのデータ移動等は実施されない仕様になっていました。

しかし、PostgreSQL 11 では、パーティションキーを更新すると更新後の値に応じて子テーブル間でデータが移動される機能が実装される予定となっています。

今回は PostgreSQL 11beta3 を使って、このパーティションキーを更新した際の動作を試してみようと思います。

■検証 (PostgreSQL 10 の動作確認)

まずは PostgreSQL 10 の動作を確認してみます。(以下の例では LIST パーティションを使用しています)

postgres=# CREATE TABLE hoge (list_key int, data text) PARTITION BY LIST (list_key);
CREATE TABLE
postgres=# CREATE TABLE hoge_child_1 PARTITION OF hoge FOR VALUES IN (1);
CREATE TABLE
postgres=# CREATE TABLE hoge_child_2 PARTITION OF hoge FOR VALUES IN (2);
CREATE TABLE
postgres=# CREATE TABLE hoge_child_3 PARTITION OF hoge FOR VALUES IN (3);
CREATE TABLE
postgres=# 
postgres=# \d+ hoge
                                     Table "public.hoge"
  Column  |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
----------+---------+-----------+----------+---------+----------+--------------+-------------
 list_key | integer |           |          |         | plain    |              | 
 data     | text    |           |          |         | extended |              | 
Partition key: LIST (list_key)
Partitions: hoge_child_1 FOR VALUES IN (1),
            hoge_child_2 FOR VALUES IN (2),
            hoge_child_3 FOR VALUES IN (3)

上記テーブルに対して、まず list_key = 1 のレコードを INSERT します。すると、パーティショニングされたテーブル “hoge” にレコードが INSERT され、実際には子テーブル “hoge_child_1” にレコードが格納されていることが確認できます。

postgres=# INSERT INTO hoge VALUES (1, 'hogehoge');
INSERT 0 1
postgres=# 
postgres=# SELECT * FROM hoge;
 list_key |   data   
----------+----------
        1 | hogehoge
(1 row)

postgres=# 
postgres=# SELECT * FROM hoge_child_1;
 list_key |   data   
----------+----------
        1 | hogehoge
(1 row)

postgres=# 
postgres=# SELECT * FROM hoge_child_2;
 list_key | data 
----------+------
(0 rows)

postgres=# 
postgres=# SELECT * FROM hoge_child_3;
 list_key | data 
----------+------
(0 rows)

この状態で list_key の値を “2” に UPDATE しようとすると、以下の通り ERROR となってしまいます。これが PostgreSQL 10 の宣言的パーティショニングの仕様動作でした。

postgres=# UPDATE hoge SET list_key = 2 WHERE data = 'hogehoge';
ERROR:  new row for relation "hoge_child_1" violates partition constraint
DETAIL:  Failing row contains (2, hogehoge).

■検証 (PostgreSQL 11 の動作確認)

それでは、PostgreSQL 11beta3 で同じ処理を実行してみます。

まずは、前述した PostgreSQL 10 の検証と同じテーブルを作成します。

postgres=# CREATE TABLE hoge (list_key int, data text) PARTITION BY LIST (list_key);
CREATE TABLE
postgres=# CREATE TABLE hoge_child_1 PARTITION OF hoge FOR VALUES IN (1);
CREATE TABLE
postgres=# CREATE TABLE hoge_child_2 PARTITION OF hoge FOR VALUES IN (2);
CREATE TABLE
postgres=# CREATE TABLE hoge_child_3 PARTITION OF hoge FOR VALUES IN (3);
CREATE TABLE
postgres=# 
postgres=# \d+ hoge
                                     Table "public.hoge"
  Column  |  Type   | Collation | Nullable | Default | Storage  | Stats target | Description 
----------+---------+-----------+----------+---------+----------+--------------+-------------
 list_key | integer |           |          |         | plain    |              | 
 data     | text    |           |          |         | extended |              | 
Partition key: LIST (list_key)
Partitions: hoge_child_1 FOR VALUES IN (1),
            hoge_child_2 FOR VALUES IN (2),
            hoge_child_3 FOR VALUES IN (3)

前述した PostgreSQL 10 の検証と同様に、list_key = 1 のレコードを INSERT し、子テーブル “hoge_child_1” にレコードが格納されていることを確認します。

postgres=# INSERT INTO hoge VALUES (1, 'hogehoge');
INSERT 0 1
postgres=# 
postgres=# SELECT * FROM hoge;
 list_key |   data   
----------+----------
        1 | hogehoge
(1 row)

postgres=# 
postgres=# SELECT * FROM hoge_child_1;
 list_key |   data   
----------+----------
        1 | hogehoge
(1 row)

postgres=# 
postgres=# SELECT * FROM hoge_child_2;
 list_key | data 
----------+------
(0 rows)

postgres=# 
postgres=# SELECT * FROM hoge_child_3;
 list_key | data 
----------+------
(0 rows)

この状態で list_key の値を “2” に UPDATE してみます。すると、PostgreSQL 10 の様に ERROR にはならずに、正常に UPDATE が実行されます。

postgres=# UPDATE hoge SET list_key = 2 WHERE data = 'hogehoge';
UPDATE 1

上記 UPDATE 実行後に各テーブルの内容を参照してみると、list_key の値を “2” に UPDATE した “data = ‘hogehoge'” のレコードが、”hoge_child_1″ から “hoge_child_2” に移動していることが確認できます。

postgres=# SELECT * FROM hoge;
 list_key |   data   
----------+----------
        2 | hogehoge
(1 row)

postgres=# 
postgres=# SELECT * FROM hoge_child_1;
 list_key | data 
----------+------
(0 rows)

postgres=# 
postgres=# SELECT * FROM hoge_child_2;
 list_key |   data   
----------+----------
        2 | hogehoge
(1 row)

postgres=# 
postgres=# SELECT * FROM hoge_child_3;
 list_key | data 
----------+------
(0 rows)

この様に、PostgreSQL 11 ではパーティションキーを UPDATE した際に適切な子テーブル (UPDATE 後の値が条件に合致する子テーブル) にレコードが移動されるようになっていることが確認できました。

■最後に

今回検証を実施した通り、PostgreSQL 11 ではパーティションキーを UPDATE した際に適切な子テーブルにレコードが移動されるため、パーティションキーを更新する可能性があるようなテーブルを作成することも可能になりました。PostgreSQL 11 では、その他にもパーティションに関連する複数の機能が強化されているため、PostgreSQL におけるパーティショニングがどんどん便利になっている様に感じます。

PostgreSQL 11 ではパーティション関連の機能を含め様々な機能が強化されているので、次回も PostgreSQL 11 の新機能の検証を実施してみようと思います。

アバター画像
About サイオステクノロジーの中の人 41 Articles
サイオステクノロジーで働く中の人です。
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

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

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


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる