1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PostgreSQL 17がやってくる(6) ネストしたパーティションの分割

Posted at

はじめに

にゃーん。
今回は小ネタ。
前回の記事(PostgreSQL 17がやってくる(5) パーティションの分割&マージ )でPostgreSQL 17で入るパーティションの分割とマージについて書いたけど、少し気になることがあったので追加で確認してみた。

ネストしたパーティション

PostgrSQLのパーティションはねストすることができる。
例えば、

test
+-- test_2023
+-- test_2024
|   +--- 2024_1q
|   +--- 2024_2q
|   +--- 2024_3q
|   +--- 2024_4q
+-- test_2025

のように、日付をレンジキーにして、test_2023,test_2024,test_2025のように分割し、更にtest_2024も日付をレンジキーにして、test_2024_1q,test_2024_2q,test_2024_3q,test_2024_4qのようにネストしたパーティションを構成することができる。

psqlの\d+メタコマンドで見るとこんな感じ。

postgres@test=# \d+ test
                                      Partitioned table "public.test"
  Column  |  Type   | Collation | Nullable | Default | Storage  | Compression | Stats target | Description
----------+---------+-----------+----------+---------+----------+-------------+--------------+-------------
 id       | integer |           |          |         | plain    |             |              |
 part_key | date    |           |          |         | plain    |             |              |
 data     | text    |           |          |         | extended |             |              |
Partition key: RANGE (part_key)
Partitions: test_2023 FOR VALUES FROM ('2023-01-01') TO ('2024-01-01'),
            test_2024 FOR VALUES FROM ('2024-01-01') TO ('2025-01-01'), PARTITIONED,
            test_2025 FOR VALUES FROM ('2025-01-01') TO ('2026-01-01'),
            test_default DEFAULT

postgres@test=# \d+ test_2024
                                   Partitioned table "public.test_2024"
  Column  |  Type   | Collation | Nullable | Default | Storage  | Compression | Stats target | Description
----------+---------+-----------+----------+---------+----------+-------------+--------------+-------------
 id       | integer |           |          |         | plain    |             |              |
 part_key | date    |           |          |         | plain    |             |              |
 data     | text    |           |          |         | extended |             |              |
Partition of: test FOR VALUES FROM ('2024-01-01') TO ('2025-01-01')
Partition constraint: ((part_key IS NOT NULL) AND (part_key >= '2024-01-01'::date) AND (part_key < '2025-01-01'::date))
Partition key: RANGE (part_key)
Partitions: test_2024_1q FOR VALUES FROM ('2024-01-01') TO ('2024-04-01'),
            test_2024_2q FOR VALUES FROM ('2024-04-01') TO ('2024-07-01'),
            test_2024_3q FOR VALUES FROM ('2024-07-01') TO ('2024-10-01'),
            test_2024_4q FOR VALUES FROM ('2024-10-01') TO ('2025-01-01')

postgres@test=# 

ネストしたパーティションの分割

検証時のバージョン

2024-05-10(commit 31e8f4e619d9b5856fa2bd5713cb1e2e170a9c7d)を使って検証した。

検証内容

最初に示した中間階層test_2024のパーティションを指定して、月単位に一気に分割できるか確認してみる。

$ psql test -ef split_year2month.sql
Null display is "(null)".
ALTER TABLE test_2024 SPLIT PARTITION test_2024 INTO
  (
    PARTITION test_01m FOR VALUES FROM ('2024-01-01') TO ('2024-02-01'),
    PARTITION test_02m FOR VALUES FROM ('2024-02-01') TO ('2024-03-01'),
    PARTITION test_03m FOR VALUES FROM ('2024-03-01') TO ('2024-04-01'),
    PARTITION test_01m FOR VALUES FROM ('2024-04-01') TO ('2024-05-01'),
    PARTITION test_02m FOR VALUES FROM ('2024-05-01') TO ('2024-06-01'),
    PARTITION test_03m FOR VALUES FROM ('2024-06-01') TO ('2024-07-01'),
    PARTITION test_01m FOR VALUES FROM ('2024-07-01') TO ('2024-08-01'),
    PARTITION test_02m FOR VALUES FROM ('2024-08-01') TO ('2024-09-01'),
    PARTITION test_03m FOR VALUES FROM ('2024-09-01') TO ('2024-10-01'),
    PARTITION test_01m FOR VALUES FROM ('2024-10-01') TO ('2024-11-01'),
    PARTITION test_02m FOR VALUES FROM ('2024-11-01') TO ('2024-12-01'),
    PARTITION test_03m FOR VALUES FROM ('2024-12-01') TO ('2025-01-01')
  );
psql:split_year2month.sql:15: ERROR:  "test_2024" is not a table
$

ダメでした。

分割対象のtest_2024を指定したけど、not a tableと怒られてしまう。
いや、test_2024もPARTITIONEDではあるけどtableじゃないの?と一瞬思ったけど、たぶん実際にデータが格納されている末端のテーブルじゃないからダメなのかも。
(PARTITIONEDの種別がついているとダメっぽい)

なので、パーティションを分割する場合には、SPLITの対象には、実際にデータが格納されている末端の階層のパーティションを指定しないとダメっぽい。

今回の場合だと、test_2024を分割した末端の階層(test_2024_1q,test_2024_2q,test_2024_3q,test_2024_4q)ごとにALTER TABLE ... SPLITコマンドを発行する必要がある。

$ psql test -ef split_quarter2month.sql
Null display is "(null)".
ALTER TABLE test_2024 SPLIT PARTITION test_2024_1q INTO
  (
    PARTITION test_2024_01m FOR VALUES FROM ('2024-01-01') TO ('2024-02-01'),
    PARTITION test_2024_02m FOR VALUES FROM ('2024-02-01') TO ('2024-03-01'),
    PARTITION test_2024_03m FOR VALUES FROM ('2024-03-01') TO ('2024-04-01')
  );
ALTER TABLE
ALTER TABLE test_2024 SPLIT PARTITION test_2024_2q INTO
  (
    PARTITION test_2024_04m FOR VALUES FROM ('2024-04-01') TO ('2024-05-01'),
    PARTITION test_2024_05m FOR VALUES FROM ('2024-05-01') TO ('2024-06-01'),
    PARTITION test_2024_06m FOR VALUES FROM ('2024-06-01') TO ('2024-07-01')
  );
ALTER TABLE
ALTER TABLE test_2024 SPLIT PARTITION test_2024_3q INTO
  (
    PARTITION test_2024_07m FOR VALUES FROM ('2024-07-01') TO ('2024-08-01'),
    PARTITION test_2024_08m FOR VALUES FROM ('2024-08-01') TO ('2024-09-01'),
    PARTITION test_2024_09m FOR VALUES FROM ('2024-09-01') TO ('2024-10-01')
  );
ALTER TABLE
ALTER TABLE test_2024 SPLIT PARTITION test_2024_4q INTO
  (
    PARTITION test_2024_10m FOR VALUES FROM ('2024-10-01') TO ('2024-11-01'),
    PARTITION test_2024_11m FOR VALUES FROM ('2024-11-01') TO ('2024-12-01'),
    PARTITION test_2024_12m FOR VALUES FROM ('2024-12-01') TO ('2025-01-01')
  );
ALTER TABLE
$

おわりに

ALTER TABLE ... SPLITコマンドでは、中間の階層のパーティションを指定して、一気に分割はできないことがわかった。
複数段のパーティションテーブルを設計する場合の注意点が分かったのでヨシ!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?