PostgreSQLエンタープライズ・コンソーシアム 技術部会 WG#3

2018年度WG3活動報告書
パーティショニング調査編

PostgreSQL Enterprise Consortium

目次
目次
1. 改訂履歴
2. ライセンス3. はじめに3.1. PostgreSQLエンタープライズコンソーシアムとWG3について
3.2. 本資料の概要と目的
3.3. 本資料の構成
3.4. 想定読者
4. PostgreSQLにおけるパーティションニング
4.1. パーティショニングの目的
4.1.1. 性能の向上
4.1.2. 運用性の向上
4.2. 継承を使用したパーティショニング
4.3. 宣言的パーティショニング
4.4. PostgreSQL 11新機能
4.4.1. 機能系
4.4.2. 性能系
5. パーティションテーブルの管理
5.1. テーブル
5.1.1. テーブル管理SQL
5.2. インデックス
5.2.1. Oracleのパーティションインデックス種類
5.2.2. インデックス管理SQL
5.2.3. 索引作成のカスケード
5.2.4. 親テーブル管理の索引の削除
5.2.5. プライマリキーの作成
6. パーティションテーブルの性能
6.1. パフォーマンス検証の方針とテーマ
6.1.1. 検証方針
6.1.2. 検証テーマ
6.2. 検証構成
6.2.1. 検証ハードウェア構成
6.2.2. 検証ソフトウェア構成
6.2.3. PostgreSQLパラメータ
6.3. 使用データ
6.3.1. lineorderテーブル
6.3.2. 使用するパーティションテーブル
6.3.3. 各方式で共通の手順
6.4. COPY FROM
6.4.1. 検証方法（COPY FROM）
6.4.2. 結果（COPY FROM）
6.4.3. 考察（COPY FROM）
6.5. INSERT
6.5.1. 検証方法（INSERT）
6.5.2. 結果（INSERT）
6.5.3. 考察（INSERT）
6.6. アナライズ
6.6.1. 検証方法（アナライズ）
6.6.2. 結果（アナライズ）
6.6.3. 考察（アナライズ）
6.7. テーブル走査（索引がない場合）
6.7.1. 検証方法（索引がない場合）
6.7.2. 結果（索引がない場合）
6.7.3. 考察（索引がない場合）
6.8. テーブル走査（索引がある場合）
6.8.1. 検証方法（索引がある場合）
6.8.2. 結果（索引がある場合）
Page 2 of 41

2
5
6
7
7
7
7
7
8
8
8
8
9
10
11
11
11
12
12
12
12
12
13
14
15
16
17
17
17
17
17
17
17
17
18
18
18
19
19
19
19
20
20
20
20
21
21
21
21
22
23
23
24
24
24
24
25

PostgreSQL Enterprise Consortium

6.8.3. 考察（索引がある場合）
6.9. パラレル走査
6.9.1. 検証方法（パラレル）
6.9.2. 結果（パラレル）
6.9.3. 考察（パラレル）6.10. 集計処理
6.10.1. 検証方法（集計）6.10.2. 結果（集計）6.10.3. 考察（集計）6.11. コンポジット構成
6.11.1. 検証方法（コンポジット）
6.11.2. 結果（コンポジット）
6.11.3. 考察（コンポジット）
6.12. パーティションテーブル同士の結合
6.12.1. 検証方法（結合）6.12.2. 結果（結合）6.12.3. 考察（結合）6.13. DELETEとTRUNCATE
6.13.1. 検証方法（DELETEとTRUNCATE）
6.13.2. 結果（DELETEとTRUNCATE）
6.13.3. 考察（DELETEとTRUNCATE）
6.14. パーティショニング性能検証のまとめ
6.14.1. 挿入処理
6.14.2. 索引走査とプルーニング
6.14.3. 適切なパーティション数
6.14.4. パーティション数と実行計画
6.14.5. PostgreSQL 11新機能
6.14.6. 削除処理
7. パーティションテーブルのTips
7.1. パーティションが変更になるUPDATE
7.2. プルーニング適用条件
7.3. パーティションテーブルおよびパーティションの一覧表示
7.3.1. パーティションテーブルの一覧表示
7.3.2. パーティションの一覧表示
7.3.3. パーティション範囲の表示
7.4. パーティションテーブルの統計情報
7.5. パーティションテーブルを指定できないコマンド
8. まとめ8.1. 宣言的パーティショニングの実装
8.2. 宣言的パーティショニングの進化
9. 著者

Page 3 of 41

25
25
26
26
27
27
27
27
28
29
29
30
30
30
30
31
31
32
33
33
33
34
34
34
34
34
34
35
36
36
36
36
37
37
37
38
39
40
40
40
41

PostgreSQL Enterprise Consortium

Page 4 of 41

PostgreSQL Enterprise Consortium

1. 改訂履歴
版

1.0

改訂日

変更内容

2019/03/13 2018 年度版として新規作成- Po stgreSQL 10 および11 を対象バージョンとする

Page 5 of 41

PostgreSQL Enterprise Consortium

2. ライセンス
本作品はCC-B Yライセンスによって許諾されています。 ライセンスの内容を知りたい方は こちら でご確認ください。 文書の内容、表記に関する誤り、ご要望、感想等につきましては、PG ECo n s のサイト を通じてお寄せいただきますようお願いいたします。

Eclip se は、Eclip se Fo u n datio n In c の米国、およびその他の国における商標もしくは登録商標です。
IB M およびDB 2 は、世界の多くの国で登録された In tern atio n al B u sin ess Mach in es Co rp o ratio n の商標です。
In tel 、インテルおよびXeo n は、米国およびその他の国における In tel Co rp o ratio n の商標です。
Java は、O racle Co rp o ratio n 及びその子会社、関連会社の米国及びその他の国における登録商標です。 文中の社名、商品名等は各社の商標または登録商標である場合があります。
Lin u x は、Lin u s To rvalds 氏の日本およびその他の国における登録商標または商標です。
Red Hat およびSh ado w man lo go は、米国およびその他の国におけるRed Hat,In c. の商標または登録商標です。
Micro so ft 、W in do w s Server 、SQL Server 、米国 Micro so ft Co rp o ratio n の米国及びその他の国における登録商標または商標です。
MySQL は、O racle Co rp o ratio n 及びその子会社、関連会社の米国及びその他の国における登録商標です。 文中の社名、商品名等は各社の商標または登録商標である場合があります。
O racle は、O racle Co rp o ratio n 及びその子会社、関連会社の米国及びその他の国における登録商標です。 文中の社名、商品名等は各社の商標または登録商標である場合があります。
Po stgreSQL は、Po stgreSQL Co mmu n ity Asso ciatio n o f Can ada のカナダにおける登録商標およびその他の国における商標です。
W in do w s は米国 Micro so ft Co rp o ratio n の米国およびその他の国における登録商標です。
TPC, TPC B en ch mark, TPC-B , TPC-C, TPC-E, tp mC, TPC-H, TPC-DS, Qp h H は米国Tran sactio n Pro cessin g Perfo rman ce Co u n cil の商標です。
その他、本資料に記載されている社名及び商品名はそれぞれ各社が 商標または登録商標として使用している場合があります 。

Page 6 of 41

PostgreSQL Enterprise Consortium

3. はじめに3.1. PostgreSQLエンタープライズコンソーシアムとWG3について
Po stgreSQL エンタープライズコンソーシアム(略称 PG ECo n s)は、Po stgreSQL 本体および各種ツールの情報収集と提供、整備などの活動を通じて、ミッションクリティカル性の高いエンタープライズ領域へのPo stgreSQL の普及を推進することを目的として設立された団体です。
PG ECo n s 技術部会ではPo stgreSQL の普及に資する課題を活動テーマとし、3 つのワーキンググループで具体的な活動を行っています。
W G 1 （新技術検証ワーキンググループ）
W G 2 （移行ワーキンググループ）
W G 3 （課題検討ワーキンググループ）
これら 3 つのワーキンググループのうち、W G 1 、W G 3 については 2015 年度まではそれぞれ、「性能ワーキンググループ」、「設計運用ワーキンググループ」という名称で活動してきました。2016 年度は、従来の活動領域を広げる意図のもとでそれらを再定義し、上記のような名称に改めました。
これに伴い、W G 3 ではPo stgreSQL の設計運用を中心としたさまざまな課題の解決のための調査検証を行い、Po stgreSQL が広く活用される事を推進していくこととしました。

3.2. 本資料の概要と目的
爆発的なデータ増加が見込まれる昨今において、大規模データへの対応はますます重要性を増しています。 大規模データへの対応策は、「データ分割」「並行処理」「データ圧縮」の3 つが挙げられます。 ここでは「データ分割」の1 手法であるテーブル・パーティションニングを取り上げます。
本資料はW G 3 の2018 年度の活動として Po stgreSQL10 から実装された宣言的パーティション機能について、 管理性や性能について調査検討した結果をまとめたものです。 パーティション設計の参考になれば幸いです。

3.3. 本資料の構成
Po stgreSQL におけるパーティション
パーティションの管理
パーティションの性能
パーティションのTip s
まとめ

3.4. 想定読者
本資料の読者は以下のような知識を有していることを想定しています。

DB MS を操作してデータベースの構築、保守、運用を行う DB A の知識
Po stgreSQL を利用する上での基礎的な知識

Page 7 of 41

PostgreSQL Enterprise Consortium

4. PostgreSQLにおけるパーティションニング
テーブル・パーティショニングとは、論理的には1 つの大きなテーブルであるものを物理的に小さなテーブルに分割することです。 Po stgreSQL 9.6 以前は、後述する継承を使用したパーティショニング、Po stgreSQL 10 以降では加えて宣言的パーティショニングを利用できます。 なお、パーティション機能はO racle など多くのデータベースにおいても実装されており、Po stgreSQL におけるパーティションも 目的やメリットにおいて多くの類似点があります。
この章では、パーティションの目的および継承を使用したパーティショニングと宣言的パーティショニングの概要および特性について簡単に紹介します。

4.1. パーティショニングの目的
論理的に一つのテーブルを物理的に複数のテーブルに分割することで後述する様々な利点を得られます。

4.1.1. 性能の 向上
頻繁に検索されるテーブル内のデータを一つのパーティションまたは一部のパーティションに格納することで、 物理的に 1 つのテーブルで構成した場合と比較してパーティション
毎のサイズや索引サイズが小さくなるため、 パーティションやその索引内のよく使用される部分がメモリに乗りやすくなります。 また条件指定を付けた SQL で全表スキャンが選択された場合にも、1 つの大規模なテーブルをすべて読み込むのではなく、 対象のデータが含まれる一部のパーティションだけを読み込むことができるため性能の向上が期待できます。
通常の大規模テーブルを検索する場合とパーティションテーブルを検索する場合の図4.1.2. 運用性の 向上
テーブル内のデータを分割して保存することで一括でのデータロードや削除が、パーティションの追加や削除で行える場合あります。 例えば、1 つの大規模なテーブルで大量のデータを削除する場合は、大量のDELETE 文による負荷とそれに伴う VACU U M による負荷が 発生します。パーティションテーブルであれば、DRO P TAB LE やTRU NCATE
でパーティションやそのデータごと削除できる場合があるため 上述の負荷をかけず高速に大量データを削除することが可能になります。
使用頻度の高いデータをSSD など高価で高性能な記憶メディアに配置し、使用頻度の低いデータを安価で遅い記憶メディアに配置することも可能です。
なお、データ分割方法としては主に以下の3 種類があります。
範囲（レンジ）パーティション
日付や特定のビジネスオブジェクトの識別子などの範囲（レンジ）でデータを分割する方法です。 データの範囲を指定して SQL を実行する場合に有効です。
年毎の範囲でテーブルのデータを分割した範囲パーティションの図

Page 8 of 41

PostgreSQL Enterprise Consortium
リストパーティション
会社の拠点や都道府県など不連続な値のリストを元にデータを分割する方法です。 不連続な列の値を指定して SQL を実行する場合に有効です。
都道府県毎にテーブルのデータを分割したリストパーティションの図

ハッシュパーティション
列のハッシュ値を元にデータを分割する方法です。 テーブルのデータを均等に分割する場合に有効です。
テーブルのデータをバッシュ分割したハッシュパーティションの図

4.2. 継承を使用したパーティショニング
テーブルの「継承」と「 CHECK 制約」と「トリガー」の機能を使用してデータを分割するパーティションの実装方法です。 Po stgreSQL 9.6 以前のバージョンでパーティショニン
グを行うには、この方法を採用する必要があります。 後述する宣言的パーティショニングより柔軟な構成が行えるという点では優れていますが、データ挿入時の性能が劣っている点や パーティションの構築手順が煩雑である点から、Po stgreSQL 10 以降では宣言的パーティショニングを採用することが一般的です。
以下に、継承を使用したパーティションテーブルを作成する手順を紹介します。 以下の例では、従業員の情報を管理するemp lo yee 表のデータを入社日時（ HIREDATE列）の年度毎に分けています。

(1) パーティションテーブル（親テーブル）の作成

CREATE TABLE employee_range(EMPLOYEE_ID
INT,
NAME
VARCHAR(10),HIREDATEDATE NOT NULL,LOCATION
VARCHAR(20));(2) 各月のパーティション（子テーブル）作成
CHECK制約でHIREDATE 列の期間を指定し、INHERIT（継承）で親テーブル名を指定します。

Page 9 of 41

PostgreSQL Enterprise Consortium

CREATE TABLE employee_range_201801 (CHECK ( HIREDATE >= DATE '2018-01-01' AND HIREDATE < DATE '2018-02-01')) INHERITS (employee_range);
CREATE TABLE employee_range_201802 (CHECK ( HIREDATE >= DATE '2018-02-01' AND HIREDATE < DATE '2018-03-01')) INHERITS (employee_range);
CREATE TABLE employee_range_201803 (CHECK ( HIREDATE >= DATE '2018-03-01' AND HIREDATE < DATE '2018-04-01')) INHERITS (employee_range);～ 中略 ～

CREATE TABLE employee_range_201812 (CHECK ( HIREDATE >= DATE '2018-12-01' AND HIREDATE < DATE '2019-01-01')) INHERITS (employee_range);(3) パーティションキーの索引作成

CREATE INDEX employee_range_ind_201801 ON employee_range_201801 (HIREDATE);
CREATE INDEX employee_range_ind_201802 ON employee_range_201802 (HIREDATE);
CREATE INDEX employee_range_ind_201803 ON employee_range_201803 (HIREDATE);～ 中略 ～

CREATE INDEX employee_range_ind_201812 ON employee_range_201812 (HIREDATE);(4) トリガーファンクションの作成

CREATE OR REPLACE FUNCTION employee_range_insert_trigger()
RETURNS TRIGGER AS$$
DECLARE
part text;
BEGIN
part := 'employee_range_' || to_char(new.hiredate, 'YYYYMM');EXECUTE 'INSERT INTO ' || part || ' VALUES(($1).*)' USING new;
RETURN NULL;END;$$LANGUAGE plpgsql;(5) トリガーの作成（上記トリガーファンクションを呼び出す）

CREATE TRIGGER employee_range_insert_trigger
BEFORE INSERT ON employee_range
FOR EACH ROW EXECUTE PROCEDURE employee_range_insert_trigger();

4.3. 宣言的パーティショニング
CREATE TAB LE 構文でPARTITIO N B Y句にパーティション方針（範囲／リスト／ハッシュ）とパーティションキーを 指定してデータを分割するパーティションの実装方法です。
Po stgreSQL 10 以降のバージョンで使用できます。 上述した継承を使用したパーティショニングに比べると以下のような制限がありますが、データ挿入時の性能やCREATE TAB LE 構文で簡単にパーティションを構築できる点などから、Po stgreSQL 10 以降では宣言的パーティショニングが 採用されることが多くなっています。
パーティションテーブルでは主キーがサポートされない
一意制約や排他制約は個々のパーティション上にのみ作成可能
別のパーティションをまたがるU PDATE はできない(Po stgreSQL 10 のみの制限)
行トリガーが必要であれば、パーティションテーブルではなく、個々のパーティションに定義する必要がある
一時リレーションと永続的リレーションを同じパーティションツリーに混合することはできない
以下に、継承を使用したパーティショニングで作成したパーティションテーブルと同じものを宣言的パーティショニングで構築する手順を紹介します。 継承を使用したパーティ
ションの構築手順よりも短い手順でパーティションテーブルを作成できます。

(1) 親テーブルの作成

Page 10 of 41

PostgreSQL Enterprise Consortium

CREATE TABLE employee_range(EMPLOYEE_ID INT,
NAME VARCHAR(10),HIREDATE DATE NOT NULL,LOCATION VARCHAR(20))
PARTITION BY RANGE (HIREDATE);(2) 各月それぞれのパーティションテーブル（子テーブル）を作成

CREATE TABLE employee_range_201801 PARTITION OF employee_range
FOR VALUES FROM ('2018-01-01') TO ('2018-02-01');
CREATE TABLE employee_range_201802 PARTITION OF employee_range
FOR VALUES FROM ('2018-02-01') TO ('2018-03-01');
CREATE TABLE employee_range_201803 PARTITION OF employee_range
FOR VALUES FROM ('2018-03-01') TO ('2018-04-01');～ 中略 ～

CREATE TABLE employee_range_201812 PARTITION OF employee_range
FOR VALUES FROM ('2018-12-01') TO ('2019-01-01');(3) パーティションキーの列に索引を作成

CREATE INDEX employee_range_ind_201801 ON employee_range_201801 (HIREDATE);
CREATE INDEX employee_range_ind_201802 ON employee_range_201802 (HIREDATE);
CREATE INDEX employee_range_ind_201803 ON employee_range_201803 (HIREDATE);～ 中略 ～

CREATE INDEX employee_range_ind_201812 ON employee_range_201812 (HIREDATE);

4.4. PostgreSQL 11新機能
Po stgreSQL 10 で実装された宣言的パーティショニングはPo stgreSQL 11 で以下の新機能が実装されています。
今後も更なる発展が期待されます。

4.4.1. 機能系
パーティションを跨る更新
デフォルトパーティションの設定
パーティションテーブルの主キー、一意キーの設定
パーティションテーブルへの外部キー
ハッシュパーティショニング
パーティションテーブルへの索引作成がパーティションへカスケードする

4.4.2. 性能系
パーティション選定の高速化
パーティション・ワイズアグリゲート
パーティション・ワイズジョイン
自動パーティションプルーニング （本検証では未実施）

Page 11 of 41

PostgreSQL Enterprise Consortium

5. パーティションテーブルの管理イメージを掴むため、O racle の管理SQL と対比します。厳密なSQL リファレンスでありません。

5.1. テーブル
5.1.1. テー ブル 管理 SQL
表記
便宜上、パーティションテーブルを「親」、パーティションを「子」と表記します。
パーティション特有のキーワードは強調表示します。
パーティションテーブル(親テーブル)： (例) p t1
パーティション(子テーブル) ： (例) p 1,p 2,…
テーブルスペース ： (例) ts1
表 5.1 テーブル管理SQL
操作
パーティション表の作成

PostgreSQL ( 宣言的パーティショ ン）

Oracle1CREATE 文で親テーブル、子テーブルを同時に作成できる
CREATE TAB LE p t1 (列定義）
PARTITIO N B Y [ RANG E | LIST | HASH ]INTERVAL () --インターバルの指定(
RANG E の場合 : PARTITIO N p 1 VALU ES LESS
THAN … ,LISTの場合 : PARTITIO N p 2 VALU ES … ,HASH の場合 : PARTITIO NS n(

親テーブルと子テーブルの数だけCREATE 文を実行する・親：CREATE TAB LE p t1 (列定義)

PARTITION [ RAN GE | LIST | HASH ] (p art_key);
・子：CREATE TAB LE p 1 PARTITION OF p t1 FOR VALUES (範囲)
RANG E の場合: FROM (xxx) TO (yyy)
LISTの場合 : IN (xxx,yyy)
HASH の場合 : WITH (M ODULUS xxx, REM AIN DER yyy)
Po stgreSQL 11 では"DEFAU LT"を指定可能

パーティションの追加

ALTER TAB LE p t1 ADD PARTITIO N p 1;

CREATE TAB LE p 1 PARTITION OF p t1 FOR VALUES...;(上記参照）

パーティションの削除

ALTER TAB LE p t1 DRO P PARTITIO N P1;

DRO P TAB LE p 1;

パーティションのデータ削除

ALTER TAB LE p t1 TRU NCATE PARTITIO N p 1;

TRU CNATE p 1;

パーティション名の変更

ALTER TAB LE p t1 RENAME PARTITIO N p 1 TO p 2;

ALTER TAB LE p 1 RENAME TO p 2;

パーティションの分割

ALTER TAB LE p t1 SPLIT PARTITIO N p 1 AT (xx);なし

パーティションのマージ

ALTER TAB LE p t1 MERG E PARTITIO NS p 1,p 2 INTOPARTITIO N p 3;

なし

パーティションの表領域移動

ALTER TAB LE p t1 MO VE PARTITIO N p 1
TAB LESPACE ts1;

ALTER TAB LE p 1 SET TAB LESPACE ts1;

パーティションの活性

ALTER TAB LE p t1 MO DIFY p 1 O NLINE;

なし

パーティションの非活性ALTER TAB LE p t1 MO DIFY p 1 O FFINE;

なし

テーブルをパーティションに変換

ALTER TAB LE p t1 ADD PARTITIO N p 1;
ALTER TAB LE p t1 EXCHANG E PARTITIO N p 1 W ITH
TAB LE t2;

ALTER TAB LE p t1 ATTACH PARTITION p 1 FOR VALUES (..);

パーティションをテーブルに変換

CREATE TAB LE t2 (..);
ALTER TAB LE p t1 EXCHANG E PARTITIO N p 1 W ITH
TAB LE t2;

ALTER TAB LE p t1 DETACH PARTITION p 1;

パーティション単位の参照

SELECT * FRO M p t1 PARTITIO N (p 1);

SELECT * FRO M p 1;

リストパーティションの値の追加ALTER TAB LE p t1 MO DIFY PARTITIO N p 1 ADD
VALU ES (val2);なし

リストパーティションの値の削
除ALTER TAB LE p t1 MO DIFY PARTITIO N p 1 DRO P
VALU ES (val2);なし

5.2. インデックス
5.2.1. Oracleの パー ティシ ョ ン イン デ ッ クス種類

Page 12 of 41

PostgreSQL Enterprise Consortium

イ ンデック ス種別

指定ワー
ド

PostgreSQL で相当する索引の可否

ローカル・同一キー索引

LO CAL可能

ローカル・非同一キー索引

LO CAL可能

グローバル・パーティション索引

G LO B AL

不可能

グローバル・非パーティション索引

なし

不可能

5.2.2. イン デ ッ クス管理 SQL
表記
便宜上、パーティションテーブルを「親」、パーティションを「子」と表記します。
パーティション特有のキーワードは強調表示します。
パーティションテーブル（親）： (例) p t1
パーティション（子）: (例) p 1,p 2,…
テーブルスペース： (例) ts1
インデックス（親）： (例) idx1
インデックス（子）： (例) idx1_p 1,…

Page 13 of 41

PostgreSQL Enterprise Consortium
表 5.2 インデックス管理SQL
操作
ローカル索引PostgreSQL ( 宣言的パーティショ ン）

OracleCREATE INDEX idx1 O N p t1 (co l1) LO CAL;CREATE INDEX idx1 O N p t1 (co l1);
親に実施した場合、親には索引定義のみ作成、各子テーブルに索引を作成。
子に実施した場合、特定子テーブルに索引を作成

グローバル・パーティション索引

CREATE INDEX idx1 O N p t1 (co l1)
G LO B AL PARTITIO N B Y RANG E (co l1)( PARTITIO N p _100 VALU ES LESS THAN (valu e1),
PARTITIO N p _1000 VALU ES LESS THAN (valu e2)
...
)

なし

グローバル・非パーティション索引

CREATE INDEX idx1 O N p t1 (co l1);なし

親テーブルの索引定義なし

CREATE INDEX idx1 O N ON LY p t1 (co l1);
親の索引に実施、定義のみ作成される親子の索引の紐づけなし

ALTER INDEX idx1 ATTACH PARTITION idx1_p 1;
親の索引と子の索引を紐付ける

索引パーティションの属性の変更なし

索引パーティションのデフォルト
属性の変更

ALTER INDEX idx1 MO DIFY DEFAU LT ATTRIB U TES

索引パーティションの表領域
移動

ALTER INDEX idx1 REB U ILD PARTITIO N p t1
PARAMETERS('TAB LESPACE= ts2');

ALTER INDEX idx1 SET TAB LESPACE ts2;

索引パーティション名の変更

ALTER INDEX idx1 RENAME PARTITIO N idx2;

ALTER INDEX idx1 RENAME TO idx2;

ALTER INDEX idx1 SET (ATTIB U TE= valu e);子の索引に実施

ALTER INDEX idx1 SET (ATTIB U TE= valu e);
親の索引に実施する事でデフォルト属性の変更に相当
子の既存索引には影響せず、以後に追加されたパーティション索引作成時に有効親の索引に実施した場合、親の索引の定義のみ変更。
子の既存索引には影響せず、以後に追加されたパーティション索引作
成時に有効。
子の索引に実施した場合、特定索引の表領域を移動。
親の索引に実施した場合、親の索引名のみ変更される。子の既存索引には影響せず、子に自動作成される索引の命名規則にも影響しない。
< 子テーブル> _< 列名> _idx
子の索引に実施した場合 、特定索引の名前を変更

索引パーティションの分割

ALTER INDEX idx1 SPLITPARTITIO N p i1 AT ( valu e ) INTOPARTITIO N p i2 ..., PARTITIO N p 3 ...);ALTER INDEX idx1 REB U ILD PARTITIO N p i2;
ALTER INDEX idx2 REB U ILD PARTITIO N p i3;なし

索引パーティションの削除(グローバル索引)ALTER INDEX idx1 DRO P PARTITIO N p 1;
ALTER INDEX idx1 REB U ILD PARTITIO N P1;(ローカル索引のパーティションは削除できない)なし

索引パーティションの再構成

ALTER INDEX idx1 REB U ILD PARTITIO N p t1;

REINDEX INDEX idx1;
単位は他に TAB LE,SCHEMA,DATAB ASE,SYSTEM がある子の索引に対して個別に実施。
親の索引にはREINDEXはできない（エラーが発生）。

5.2.3. 索引作成の カスケー ド
Po stgreSQL 11 の宣言的パーティションでは親テーブルに索引を作成する事で、子テーブルに作成されます。
（実行例）

lin eo rder_yyyyテーブルは年ごとのパーティションテーブル,

Page 14 of 41

PostgreSQL Enterprise Consortium● PostgreSQL 10 : 索引作成のカスケード不可能=# CREATE INDEX lineorder_yyyy_orderkey ON lineorder_yyyy (lo_orderkey);
ERROR: cannot create index on partitioned table "lineorder_yyyy"● PostgreSQL 11 : 索引作成のカスケード可能=# CREATE INDEX lineorder_yyyy_ordatedate ON lineorder_yyyy (lo_orderdate);
CREATE INDEXPo stgreSQL 11 では子テーブルに索引が作成されていることをシステムカタログから確認=# SELECT tablename,indexname FROM pg_indexes WHERE tablename LIKE 'lineorder_yyyy_%';tablename|indexname---------------------+-------------------------------------lineorder_yyyy_1992 | lineorder_yyyy_1992_lo_orderdate_idx
lineorder_yyyy_1993 | lineorder_yyyy_1993_lo_orderdate_idx
lineorder_yyyy_1994 | lineorder_yyyy_1994_lo_orderdate_idx
・・・略・・・(7 rows)

パーティションテーブルの索引はrelkin d = 'I' （大文字)として作成されている。サイズは0 バイト。

=# SELECT relname FROM pg_class WHERE relkind='I' AND relname LIKE 'lineorder_yyyy%';relname--------------------------lineorder_yyyy_ordatedate(1 row)=# SELECT pg_relation_size('lineorder_yyyy_ordatedate');pg_relation_size-----------------0(1 row)

注意点
索引の属性情報（テーブルスペースなど）も引き継ぐため、同一のテーブルスペースに作成される。
親テーブルに作成後に ALTER INDEX でローカル索引を指定してテーブルスペースを変更することは可能。

5.2.4. 親テー ブル 管理の 索引の 削除
親テーブルで管理されている索引は個別には削除できません。
（例） lin eo rder_yyyy_1998_lo _su p p key_idx 索引はlin eo rder_yyyy_1998 パーティションの索引=# DROP INDEX lineorder_yyyy_1998_lo_suppkey_idx;
ERROR: cannot drop index lineorder_yyyy_1998_lo_suppkey_idx because index
lineorder_yyyy_suppkey requires it

子テーブル特有の索引を作成することも可能です。
特定子テーブルに索引作成後、親テーブルにその列の索引を作成した場合、事前作成の索引がアタッチされます。
その場合、Po stgreSQL の命名規則に則った索引と独自命名の索引が混在します。
特定パーティションに索引を作成後、親テーブルに同一列の索引を作成すると、自動的に親テーブルの索引にアタッチされます。
アタッチされると個別に削除ができません。

Page 15 of 41

PostgreSQL Enterprise Consortium-- 子テーブルに索引作成=# CREATE INDEX lineorder_yyyy_1999_partkey ON lineorder_yyyy_1999 (lo_partkey);
CREATE INDEX-- 親テーブルに索引作成=# CREATE INDEX lineorder_yyyy_partkey ON lineorder_yyyy (lo_partkey);
CREATE INDEX-- 親テーブルの索引にアタッチ後、子テーブルの索引単独で削除できないことを確認=# DROP INDEX lineorder_yyyy_1999_partkey;
ERROR: cannot drop index lineorder_yyyy_1999_partkey because index
lineorder_yyyy_partkey requires it

アタッチ時にはインデックスの作成が行われるため時間を要します（その間、親テーブルはロックされた状態です）。
親テーブルのロック時間を短縮するには、事前に個別インデックスを作成しておくのが有効です。
索引作成文のO NLYオプションについて * O NLYを付与することで、既存パーティションに対して索引作成処理が実行されることを回避します。 * 親テーブルに索引定義のみ作成し、子テーブルに作成した索引をアタッチします。 * なお以後に作成されたパーティションには索引が作成されます。
（例） lin eo rder_yyyyパーティションテーブルのlo _p artkey列に対する索引-- 親テーブルに ONLYオプションを付与して索引を作成=# CREATE INDEX lineorder_yyyy_partkey ON ONLY lineorder_yyyy (lo_partkey);
CREATE INDEX-- 子テーブルに索引作成=# CREATE INDEX lineorder_yyyy_1998_partkey ON lineorder_yyyy_1998 (lo_partkey);
CREATE INDEX-- 親テーブルのインデックスに子テーブルのインデックスをアタッチ=# ALTER INDEX lineorder_yyyy_partkey ATTACH PARTITION lineorder_yyyy_1998_partkey;
ALTER INDEX

5.2.5. プライマリ キ ー の 作成
Po stgreSQL 11 では全パーティションに跨るプライマリーキーやユニークインデックスを作成することが可能となりました。
これによりパーティションテーブルのデータの整合性が高まります。
ただし索引キーにはパーティションキーを含む必要があります。

● ケース１ lin eo rder 非パーティションテーブルに lo _o rderkey列及びlo _lin en u mb er 列でプライマリーキーに作成=# ALTER TABLE lineorder ADD CONSTRAINT lineorder_pk PRIMARY KEY(lo_orderkey,lo_linenumeric);
ALTER TABLE● ケース２ lin eo rder_yyyyパーティションテーブルで同様のインデックス作成を試みるとエラーが発生=# ALTER TABLE lineorder_yyyy ADD CONSTRAINT lineorder_yyyy_pk PRIMARY KEY(lo_orderkey,lo_linenumber);
ERROR: insufficient columns in PRIMARY KEY constraint definition
DETAIL: PRIMARY KEY constraint on table "lineorder_yyyy" lacks column "lo_orderdate" whichis part of the partition key.
● ケース３ lin eo rder_yyyyパーティションテーブルでパーティションキーであるlo _o rderdate 列を列構成に含めると作成成功（配置場所は任意）=# ALTER TABLE lineorder_yyyy ADD CONSTRAINT lineorder_yyyy_pk PRIMARY KEY(lo_orderkey,lo_linenumber,lo_orderdate);
ALTER TABLE

Page 16 of 41

PostgreSQL Enterprise Consortium

6. パーティションテーブルの性能
6.1. パフォーマンス検証の方針とテーマ
6.1.1. 検証方針
シンプルなSQL による基礎的な性能検証を目的としています。 そのためスタースキーマ構成などの複雑なSQL の性能検証は実施していません。

6.1.2. 検証テー マ
宣言的パーティショニングによる挿入処理(CO PY FRO M / INSERT)の改善
継承を使用したパーティショニングの課題であった挿入処理が宣言的パーティショニングで改善されていることを確認します。
パーティションテーブルと非パーティションテーブルの特性
非パーティションテーブル/パーティションテーブルがそれぞれ優位となるケースを確認します。
パーティションの粒度（パーティション数）
年 / 年月 / 年月日 など粒度を細かくすることのメリットと注意点を確認します。
パーティション選択の高速化
パーティション選択の性能がPo stgreSQL 11 で改善されていることを確認します。
パラレルワーカによるパーティション走査の高速化
並列度を増加することで高速化することを確認します。
Po stgreSQL 11 で改善されていることを確認します。
集計処理（パーティション・ワイズアグリゲート）
集計処理の性能がPo stgreSQL 11 で改善されていることを確認します。
結合処理（パーティション・ワイズジョイン）
パーティションテーブル同士の結合処理がPo stgreSQL 11 で改善されていることを確認します。
削除処理（ DELETE/TRU NCATE ）パーティションテーブルのパーティション単位のDELETE やTRU NCATE の効果を確認します。

6.2. 検証構成
6.2.1. 検証ハー ドウ ェア構成
検証環境のハードウェア構成の概略を示します。
本性能検証ではDB サーバ上でSQL を直接実行する形式としています。
ハードウエア構成
項目

仕様

CPU

In tel Xeo n CPU E5-2640 v2 @ 2.00G Hz * 32 Co re

搭載メモリ

64G B

内蔵ストレージ 約 2TB

6.2.2. 検証ソフトウ ェア構成
検証環境のソフトウェア構成を示します。
ソフトウエア構成
項目

OS

仕様

Red Hat En terp rise Lin u x Server release 6.5 (San tiago )Po stgreSQL Po stgreSQL 10.1
Po stgreSQL 11.1

6.2.3. PostgreSQL パラメー タ
Po stgreSQL のパラメータを示します。
Po stgreSQL 11 で導入されたパラメータには(11)を付記しています。
パーティションニング関連は太字表記としています。
パラレル関連についてはパラレルの検証以外はデフォルト設定です。

Page 17 of 41

PostgreSQL Enterprise Consortium
共有バッファはテーブル(lin eo rder 系)が格納できるサイズを確保し、p g_p rew arm でメモリに配置しています。

Po stgreSQL 主要パラメータ一覧
分類

パラ メ ータ

パラレル

設定値

備考

max_p arallel_w o rkers_p er_gath er

2

デフォルト

max_p arallel_w o rkers

8

デフォルト

ch eckp o in t_timeo u t

1d

max_w al_size

100G B

暗黙的にチェックポイントを発生させない ことを目的とし
た設定

共有メモリ

sh ared_b u ffers

5G B

lin eo rder テーブルが搭載できるサイズ
処理前に p g_p rew arm でメモリに搭載

プランナ

effective_cach e_size

10G B

sh ared_b u ffers の2 倍

en ab le_p arallel_ap p en d (11)on

パラレルクエリにてパラレルAp p en d 有効

en ab le_p arallel_h ash (11)on

パラレルクエリにてパラレルHash 有効

enable_partition_pruning (11)on

パーティションプルーニング有効

enable_partitionwise_aggregate (11)on

パーティションワイズアグリゲート有効

enable_partitionwise_join (11)on

パーティションワイズジョン有効

p arallel_leader_p articip atio n (11)on

パラレルクエリにてリーダプロセスがワーカ プロセスと同様の処理を行わないw o rk_mem

1G B

ソート用メモリサイズ

main ten an ce_w o rk_mem

1G B

インデックス作成用メモリサイズ

max_lo cks_p er_tran sactio n

3000

共有ロックテーブルのエントリ数であり、 パーティション数より多く設定する

チェックポイントワークメモリ

トランザクション

6.3. 使用データ
6.3.1. lineorderテー ブル
StarSch emaB en ch mark のlin eo rder を使用しました。
h ttp s://gith u b .co m/lemire/StarSch emaB en ch mark
データはスケール4 を指定して作成しています。
表 6.1 データ件数
件数

サイ ズ

約2,400 万件

2.3G B

表 6.2 lin eo rder の年別の件数と割
合
年

件数

割合

1992

3,642,219

15.2%

1993

3,647,031

15.2%

1994

3,641,723

15.2%

1995

3,635,511

15.2%

1996

3,654,372

15.2%

1997

3,639,076

15.2%

1998

2,136,738

8.9%

最終年以外はほぼ均等に分布しています。

6.3.2. 使用するパー ティシ ョ ン テー ブル
lin eo rder テーブルを使用して、以下の各粒度で作成しています。
全てレンジパーティションによる時系列のパーティション表です。
なお検証ケースによっては別の構成を使用する場合もあります。
コンポジットパーティション
パーティションテーブル同士の結合

Page 18 of 41

PostgreSQL Enterprise Consortium
表 6.3 パーティションテーブル
実装方式

粒度 ( パーティショ ン数）

親テーブル名子テーブル名（ 例）

継承によるパーティショニング 年 (7)lin eo rder_9_yyyy

lin eo rder_9_yyyy_1992,
lin eo rder_9_yyyy_1993,...
lin eo rder_9_yyyy_1997,
lin eo rder_9_yyyy_1998

宣言的パーティショニング

年 (7)lin eo rder_yyyy

lin eo rder_yyyy_1992,
lin eo rder_yyyy_1993,...
lin eo rder_yyyy_1997,
lin eo rder_yyyy_1998

宣言的パーティショニング

年月 (84)lin eo rder_yyyymm

lin eo rder_yyyymm_199201,
lin eo rder_yyyymm_199202,...
lin eo rder_yyyymm_199811,
lin eo rder_yyyymm_199812

宣言的パーティショニング年月日 (2556)

lin eo rder_yyyymmdd

lin eo rder_yyyymmdd_19920101,
lin eo rder_yyyymmdd_19920102,...
lin eo rder_yyyymmdd_19981230,
lin eo rder_yyyymmdd_19981231

6.3.3. 各方式で 共通の 手順
基本的に以下はすべての検証ケースでセットで実行しています。

p g_p rew arm で共有メモリに載せます。パーティションテーブルを指定できないため、パーティション毎に実施します。
VACU U M を実行して、In dex O n ly Scan が効くようにします。パーティションテーブルを指定できます。

6.4. COPY FROM
継承によるパーティショニングでは挿入処理のパフォーマンスが課題の一つでした。
挿入処理はトリガーベースとなるためオーバーヘッドが発生するためです。
ここではCO PY FRO M による挿入処理を検証します。
主な確認ポイント
宣言的パーティショニングでは継承によるパーティショニングより改善していること

6.4.1. 検証方法（ COPY FROM）
以下の構成のテーブルを使用します。
表 6.4 使用するテーブル
構成

グラ フの凡例表記

非パーティションテーブル

No rmal

宣言的パーティションテーブル（年）yyyy

宣言的パーティションテーブル（年月）yyyymm

宣言的パーティションテーブル（年月日）yyyymmdd

継承によるパーティションテーブル（年）yyyy(In h eri)CSV ファイルを単一のCO PY FRO M 文にて各構成テーブルへロードします。
(非パーティション表の場合)=# CHECKPOINT;=# BEGIN;=# TRUNCATE lineorder;=# COPY lineorder FROM '/tmp/lineorder.dat' DELIMITER '|';=# COMMIT;

6.4.2. 結果（ COPY FROM）

Page 19 of 41

PostgreSQL Enterprise Consortium

CO PY FRO M の所要時間比較
青色がPo stgreSQL 10 、茶色がPo stgreSQL 11 を表しています。縦軸の目盛りを合わせています。
縦軸は時間（秒）であり、小さい方が優れています。

6.4.3. 考察（ COPY FROM）
宣言的パーティションは継承によるパーティションの5% 程度であり、圧倒的に高速化しています。
Po stgreSQL 10 とPo stgreSQL 11 では、有意な違いはありません。

6.5. INSERT
ここではINSERTによる挿入処理の処理時間を検証します。
また Po stgreSQL 11 では、パーティション選定処理が高速化されています。
多数のINSERT文を発行することで確認を試みます。
主な確認ポイント
宣言的パーティショニングでは継承によるパーティショニングより改善していること
宣言的パーティショニングにおいて、Po stgreSQL 11 はPo stgreSQL 10 より改善していること

6.5.1. 検証方法（ INSERT ）テーブル構成はCO PY FRO M と同じです。
件数分(約2,400 万件）のINSERT文を実行します。
(非パーティション表の場合)=# CHECKPOINT;=# BEGIN;=# TRUNCATE lineorder;=# INSERT INTO lineorder VALUES (...); --1件目=# INSERT INTO lineorder VALUES (...); --2件目=# INSERT INTO lineorder VALUES (...); --3件目...
=# INSERT INTO lineorder VALUES (...); --2,400万件目=# COMMIT;

6.5.2. 結果（ INSERT ）Page 20 of 41

PostgreSQL Enterprise Consortium

INSERT の所要時間比較
青色がPo stgreSQL 10 、茶色がPo stgreSQL 11 を表しています。縦軸の目盛りが異なることにご注意ください。
縦軸は時間（秒）であり、小さい方が優れています。
左は、「非パーティション表」、「宣言的パーティション(年)」、「継承によるパーティション(年)」のパーティション方式による比較です。
右は、「宣言的パーティション」に限定し、Po stgreSQL 10 とPo stgreSQL 11 の粒度毎の比較です。

6.5.3. 考察（ INSERT ）宣言的パーティションは継承によるパーティションより36% 程度時間が短縮しています（左図）。

Po stgreSQL 11 の宣言的パーティションはPo stgreSQL 10 より70% 程度時間が短縮されています（右図）。パーティション選定処理の高速化によるものと考えられます。Po stgreSQL 11 のリリースノート より
E.3.3.1.1. Partitio n in g
Allo w faster p artitio n elimin atio n du rin g qu ery p ro cessin g
Po stgreSQL 11 の宣言的パーティションでもパーティション数が増えるほど時間を要するする傾向があります（右図）。

6.6. アナライズ
アナライズはプランナ統計情報を更新する処理であり、メンテナンス作業として重要です。 パーティション数が増えることの影響度を確認します。

6.6.1. 検証方法（ アナライズ ）パーティション表では親テーブルに対してアナライズを実行します。
アナライズは親テーブルに実行すると子テーブルにカスケードして実行されます。
テーブル構成はインデックス作成と同一です。
非パーティションの場合のSQL=# ANALYZE VERBOSE lineorder;

6.6.2. 結果（ アナライズ ）Page 21 of 41

PostgreSQL Enterprise Consortium

アナライズの所要時間比較
縦軸は時間（ミリ秒）であり、小さい方が優れています。

6.6.3. 考察（ アナライズ ）パーティション表ではパーティション数に応じて所要時間が長くなる傾向にあります。
（子）テーブル毎の走査ページおよび件数にはしきい値があり、それを上回っているテーブルではサンプリングで実施します。
しきい値を下回るとサンプリングではなく全ページあるいは全件が対象となります。
表 6.5 アナライズにおけるサンプル走査ページ数および件数
構成

テーブル数

（ 子） テーブル毎の走査ページ数（ 子） テーブル毎の対象件数

非パーティションテーブル

1

30,000 ページ

30,000 件

宣言的パーティションテーブル（年）7

30,000 ページ

30,000 件

宣言的パーティションテーブル（年月）84

約 5,500 ページ (全ページ）

30,000 件

宣言的パーティションテーブル（年月日）2,556

約 180 ページ (全ページ）

約 10,000 件 (全件）

Page 22 of 41

PostgreSQL Enterprise Consortium●非パーティションテーブルの場合=# ANALYZE VERBOSE lineorder;...
INFO: "lineorder": scanned 30000 of 436302 pages, ...; 30000 rows insample, ...
●パーティションテーブル（年）の場合=# ANALYZE VERBOSE lineorder_yyyy;...
INFO: "lineorder_yyyy_1992": scanned 30000 of 66222 pages, ...; 30000 rows
in sample, ...
INFO: "lineorder_yyyy_1993": scanned 30000 of 66310 pages, ...; 30000 rows
in sample, ...
...
●パーティションテーブル（年月）の場合=# ANALYZE VERBOSE lineorder_yyyymm;...
INFO: "lineorder_yyyymm_199201": scanned 5645 of 5645 pages, ...; 30000
rows in sample, ...
INFO: "lineorder_yyyymm_199202": scanned 5259 of 5259 pages, ...; 30000
rows in sample, ...
...
●パーティションテーブル（年月日）の場合=# ANALYZE VERBOSE lineorder_yyyymmdd;...
INFO: "lineorder_yyyymmdd_19920101": scanned 179 of 179 pages, ...; 9837
rows in sample, ...
INFO: "lineorder_yyyymmdd_19920102": scanned 182 of 182 pages, ...; 9998
rows in sample, ...
...

自動アナライズにおいては更新されたパーティションのみ実施されるため、問題はないと考えられます。

6.7. テーブル走査（索引がない場合）集計処理を含まないシンプルな走査におけるパーティションの優位性を確認します。
ここでは非パーティションおよびパーティションともに条件に指定した列に索引がない場合です。

6.7.1. 検証方法（ 索引がない 場合）バージョン

Po stgreSQL 11
テーブル構成表 6.6 テーブル構成（索引がない場合）
テーブル構成グラ フの凡例表記

非パーティションテーブル

No rmal

宣言的パーティションテーブル（年）yyyy

宣言的パーティションテーブル（年月）yyyymm

宣言的パーティションテーブル（年月日）yyyymmdd

検索範囲

Page 23 of 41

PostgreSQL Enterprise Consortium
表 6.7 検索範囲（索引がない場合）
検索範囲

条件指定

グラ フの凡例表記

3日

lo _o rderdate B ETW EEN 19920101 AND 19920103

3days

3月

lo _o rderdate B ETW EEN 19920101 AND 19920331

3mo n th s

3年

lo _o rderdate B ETW EEN 19920101 AND 19941231

3years

非パーティションで検索範囲3 日の場合のSQL=# EXPLAIN (ANALYZE,BUFFERS)SELECT * FROM lineorder
WHERE lo_orderdate BETWEEN 19920101 AND 19920103;

6.7.2. 結果（ 索引がない 場合）

テーブルスキャンの所要時間（索引がある場合）
縦軸は時間（ミリ秒）であり、小さい方が優れています。

6.7.3. 考察（ 索引がない 場合）
非パーティションテーブルではSeq scan となるため、プルーニングが効くパーティションテーブルが明確に優位です。
非パーティションテーブルと年月パーティションの比較では、3 日で 96% 、3 月で 80% 、3 年で 32% 改善されています。

6.8. テーブル走査（索引がある場合）集計処理を含まないシンプルな走査におけるパーティションの優位性を確認します。
ここでは非パーティションテーブルおよびパーティションテーブルともに条件に指定した列に索引がある場合です。
索引は通常の B-Tree イ ンデック ス を使用しています。
意思決定支援システム用途としては BRIN イ ンデック ス も有力ですが、以下の理由から取り止めました。
通常のB *Tree 索引で高速であったため
データ挿入が頻繁に行われるシステムを想定しているため

6.8.1. 検証方法（ 索引があ る場合）
バージョン

Po stgreSQL 11
テーブル構成Page 24 of 41

PostgreSQL Enterprise Consortium
表 6.8 テーブル構成（索引がない場合）
構成

グラ フの凡例表記

非パーティションテーブル

No rmal

宣言的パーティションテーブル（年）yyyy

宣言的パーティションテーブル（年月）yyyymm

宣言的パーティションテーブル（年月日）yyyymmdd

検索範囲
表 6.9 検索範囲（索引がある場合）
検索範囲

条件指定

グラ フの凡例表記

3日

lo _o rderdate B ETW EEN 19920101 AND 19920103

3days

3月

lo _o rderdate B ETW EEN 19920101 AND 19920331

3mo n th s

3年

lo _o rderdate B ETW EEN 19920101 AND 19941231

3years

非パーティションで検索範囲3 日の場合のSQL=# EXPLAIN (ANALYZE,BUFFERS)SELECT * FROM lineorder
WHERE lo_orderdate BETWEEN 19920101 AND 19920103;

6.8.2. 結果（ 索引があ る場合）

テーブルスキャンの所要時間（索引あり）
縦軸は時間（ミリ秒）であり、小さい方が優れています。
左がPo stgreSQL 10 、右がPo stgreSQL 11 です。 縦軸の目盛りを合わせています。

6.8.3. 考察（ 索引があ る場合）
非パーティション表も索引があると限定的な範囲ではパーティション表と遜色ありません。
ただし索引走査は検索範囲が一定割合を超えると 全表走査に 切り 替わる ため、パーティションより遅くなります。
パーティションプルーニングは安定して動作します。

6.9. パラレル走査
パーティションテーブルにおけるパラレルクエリの影響度を検証します。

Page 25 of 41

PostgreSQL Enterprise Consortium

Po stgreSQL 11 においてパーティション走査が改善されていること
並列度（ワーカー数）を増加することで高速化すること
なお日付条件は指定しないこととします。

6.9.1. 検証方法（ パラレル ）重要度列(lo _o rderp rio rity)に索引を作成し、索引が使用される条件を付与します。
パラレル度を 2,4,6 と増加させて構成毎の効果の有無を確認します。
日付条件を指定しないため、パーティションテーブルではプルーニングは行いません。
バージョン

Po stgreSQL 10 および Po stgreSQL 11
テーブル構成表 6.10 テーブル構成
構成

グラ フの凡例表記

非パーティションテーブル

No rmal

宣言的パーティションテーブル（年）yyyy

宣言的パーティションテーブル（年月）yyyymm

宣言的パーティションテーブル（年月日）yyyymmdd

並列度
表 6.11 並列度
並列度

パラ メ ータ 設定

グラ フの凡例表記

並列度2

SET max_p arallel_w o rkers_p er_gath er= 2;

degree2

並列度4

SET max_p arallel_w o rkers_p er_gath er= 4;

degree4

並列度6

SET max_p arallel_w o rkers_p er_gath er= 6;

degree6

非パーティションの場合のSQL=# EXPLAIN (ANALYZE,BUFFERS)SELECT count(*) FROM lineorder
WHERE lo_orderpriority IN ('1-URGENT','2-HIGH');

6.9.2. 結果（ パラレル ）パラレルスキャンの所要時間

Page 26 of 41

PostgreSQL Enterprise Consortium
縦軸は時間（ミリ秒）であり、小さい方が優れています。
左がPo stgreSQL 10 、右がPo stgreSQL 11 です。 縦軸の目盛りを合わせています。

6.9.3. 考察（ パラレル ）Po stgreSQL 11 ではパラレル走査が高速化されています。特に年月日パーティションテーブルでの改善が顕著です。
パーティションにおけるパラレル走査の効率化によるものと考えられます。Po stgreSQL 11 のリリースノート より

E.3.3.1.2. Parallel Qu eries
Allo w p artitio n scan s to mo re efficien tly u se p arallel w o rkers
Po stgreSQL11 では並列度（ワーカー数）を増加することで高速化する余地があります。
プルーニングを行わない状況では、非パーティションテーブルが最も高速です。

6.10. 集計処理
集計処理を含む走査におけるパーティションの優位性を確認します。
非パーティション表およびパーティション表ともに条件に指定した列に索引がある場合で特性を確認します。
Po stgreSQL 11 では集計合処理が効率化されました (パーティショ ン・ ワイ ズアグリゲート ）。
Po stgreSQL 10 では各パーティションをAp p en d で統合した後に集計します。
Po stgreSQL 11 ではAp p en d 前にパーティション毎に集計することで効率化しています。
本機能を有効化するためには、以下のパラメータを設定する必要があります。
表 6.12 パラメータパラ メ ータ

設定値

en ab le_p artitio n w ise_aggregate

備考o n (有効)デフォルトはo ff(無効)6.10.1. 検証方法（ 集計）バージョン

Po stgreSQL 10 および Po stgreSQL 11
テーブル構成表 6.13 使用するテーブル
構成

グラ フの凡例表記

非パーティションテーブル

No rmal

宣言的パーティションテーブル（年）yyyy

宣言的パーティションテーブル（年月）yyyymm

宣言的パーティションテーブル（年月日）yyyymmdd

検索範囲
表 6.14 検索範囲（索引がある場合）
検索範囲

条件指定

グラ フの凡例表記

3日

lo _o rderdate B ETW EEN 19920101 AND 19920103

3days

3月

lo _o rderdate B ETW EEN 19920101 AND 19920331

3mo n th s

3年

lo _o rderdate B ETW EEN 19920101 AND 19941231

3years

範囲指定なしn o -ran ge

非パーティションで検索範囲3 日の場合のSQL=# EXPLAIN (ANALYZE,BUFFERS)SELECT count(*) FROM lineorder
WHERE lo_orderdate BETWEEN 19920101 AND 19920103;

6.10.2. 結果（ 集計）

Page 27 of 41

PostgreSQL Enterprise Consortium

集計処理の所要時間
縦軸は時間（ミリ秒）であり、小さい方が優れています。
左がPo stgreSQL 10 、右がPo stgreSQL 11 です。 縦軸の目盛りを合わせています。

6.10.3. 考察（ 集計）
Po stgreSQL 11 にて改善されていることが確認できました。
だだしPo stgreSQL11 においても非パーティションが最速となるケースが多くなっています。
パーティションの粒度としては、年月がバランスが良い結果となっています。
実行計画では以下の違いがあります。

Po stgreSQL 10 : Parallel Ap p en d → 一括Partial Aggregate
Po stgreSQL 11 : パーティション毎のPartial Aggregate → Parallel Ap p en d

●PostgreSQL 10=# EXPLAIN SELECT COUNT(*) FROM lineorder_yyyy;
QUERY PLAN--------------------------------------------------------------------------------------------Finalize Aggregate (cost=559238.45..559238.46 rows=1 width=8)-> Gather (cost=559238.24..559238.45 rows=2 width=8)
Workers Planned: 2-> Partial Aggregate (cost=558238.24..558238.25 rows=1 width=8)-> Parallel Append (cost=0.43..533241.69 rows=9998619 width=0)-> Parallel Index Only Scan using lineorder_yyyy_1996_lo_partkey_idx...
-> Parallel Index Only Scan using lineorder_yyyy_1993_lo_partkey_idx...
-> Parallel Index Only Scan using lineorder_yyyy_1992_lo_partkey_idx...
～ 中略 ～-> Parallel Index Only Scan using lineorder_yyyy_1998_lo_partkey_idx...

Page 28 of 41

PostgreSQL Enterprise Consortium●PostgreSQL 11=# EXPLAIN SELECT COUNT(*) FROM lineorder_yyyy;
QUERY PLAN--------------------------------------------------------------------------------------------Finalize Aggregate (cost=509246.68..509246.69 rows=1 width=8)-> Gather (cost=78242.82..509246.65 rows=14 width=8)
Workers Planned: 2-> Parallel Append (cost=77242.82..508245.25 rows=7 width=8)-> Partial Aggregate (cost=77397.50..77397.51 rows=1 width=8)-> Parallel Index Only Scan using lineorder_yyyy_1996_lo_partkey_idx...
-> Partial Aggregate (cost=77242.82..77242.83 rows=1 width=8)-> Parallel Index Only Scan using lineorder_yyyy_1993_lo_partkey_idx...
-> Partial Aggregate (cost=77141.25..77141.26 rows=1 width=8)-> Parallel Index Only Scan using lineorder_yyyy_1992_lo_partkey_idx...
～ 中略 ～-> Partial Aggregate (cost=45260.90..45260.91 rows=1 width=8)-> Parallel Index Only Scan using lineorder_yyyy_1998_lo_partkey_idx...

6.11. コンポジット構成
サブパーティショニングと呼ばれる手法を使用して、パーティションのパーティションとして多段に定義することができます。
パーティション表（親 ） - パーティション（子 ） - サブパーティション（孫 ）この構成では、サブパーティションにのみデータが挿入されます。
このような多段構成のパーティションはコンポジットパーティションと呼ばれます。
今回は以下のレンジ-リスト構成にて検証しました。
構成： lo _o rderdate 列（レンジ ) - lo _o rderp rio rity列（リスト ）lo _o rderp rio rity列には重要度がセットされており、以下の値がほぼ均等に配分されています。
'1-U RG ENT'
'2-HIG H''3-MEDIU M''4-NO T SPECIFIED''5-LO W '6.11.1. 検証方法（ コン ポ ジッ ト）
以下の構成のテーブルを使用します。
表 6.15 使用するテーブル
テーブル構成グラ フの凡例表記

非パーティションテーブル

No rmal

宣言的パーティションテーブル（年）yyyy

宣言的コンポジットパーティションテーブル（年-重要度）

yyyy-p ri

Po stgreSQL11 のみを対象としています。
表 6.16 検索範囲
検索範囲

条件指定

グラ フの凡例表記

3日

lo _o rderdate B ETW EEN 19920101 AND 19920103

3day

3月

lo _o rderdate B ETW EEN 19920101 AND 19920331

3mo n th3年

lo _o rderdate B ETW EEN 19920101 AND 19941231

3year

全範囲

（日付条件なし）

n o -ran ge

非パーティションで範囲3 日の検索の場合=# EXPLAIN (ANALYZE,BUFFERS)SELECT count(*) FROM lineorder
WHERE lo_orderdate BETWEEN 19920101 AND 19920103
ANDlo_orderpriority IN ('1-URGENT');

Page 29 of 41

PostgreSQL Enterprise Consortium

6.11.2. 結果（ コン ポ ジッ ト）

集計処理の所要時間
縦軸は時間（ミリ秒）であり、小さい方が優れています。

6.11.3. 考察（ コン ポ ジッ ト）
コンポジット構成に沿った日付と重要度の2 つの条件がある場合は、コンポジット構成は高い性能を発揮します。
ただし日付条件がない場合はコンポジット構成が最も時間を要しています。カスタマイズされた構成であるため汎用性は低下することにご注意ください。

6.12. パーティションテーブル同士の結合
パーティションキーが同一のパーティションテーブル同士の結合処理の性能を検証します。
Po stgreSQL 11 では同一構成のパーティションテーブルの結合処理が効率化されました (パーティショ ン・ ワイ ズジョ イ ン ）。
Po stgreSQL 10 では各パーティションをAp p en d で統合した後に結合します。
Po stgreSQL 11 ではAp p en d 前にパーティション毎に少ない件数でハッシュ結合することで効率化しています。
本機能を有効化するためには、以下のパラメータを設定する必要があります。
表 6.17 パラメータパラ メ ータ

設定値

en ab le_p artitio n w ise_jo ino n (有効)

備考
デフォルトはo ff(無効)6.12.1. 検証方法（ 結合）
それぞれ同じ粒度のパーティションテーブルを用意して結合します。
バージョン

Po stgreSQL 10 および Po stgreSQL 11
テーブル構成表 6.18 テーブル構成（結合）構成

グラ フの凡例表記

非パーティションテーブル

No rmal

宣言的パーティションテーブル（年）yyyy

宣言的パーティションテーブル（年月）yyyymm

検索範囲

Page 30 of 41

PostgreSQL Enterprise Consortium
表 6.19 検索範囲（結合）
検索範囲

条件指定

グラ フの凡例表記

3日

lo _o rderdate B ETW EEN 19920101 AND 19920103

3days

3月

lo _o rderdate B ETW EEN 19920101 AND 19920331

3mo n th s

各構成の検索範囲3 日の場合のSQL●非パーティションの場合=# EXPLAIN (ANALYZE,BUFFERS)SELECT count(*)
FROM lineorder l1,
lineorder2 l2
WHERE l1.lo_orderdate = l2.lo_orderdateANDl1.lo_orderdate between 19920101 AND 19920103;●年パーティションの場合=# EXPLAIN (ANALYZE,BUFFERS)SELECT count(*)
FROM lineorder_yyyy l1,
lineorder2_yyyy l2
WHERE l1.lo_orderdate = l2.lo_orderdateANDl1.lo_orderdate between 19920101 AND 19920103;●年月パーティションの場合=# EXPLAIN (ANALYZE,BUFFERS)SELECT count(*)
FROM lineorder_yyyymm l1,
lineorder2_yyyymm l2
WHERE l1.lo_orderdate = l2.lo_orderdateANDl1.lo_orderdate between 19920101 AND 19920103;

6.12.2. 結果（ 結合）

パーティション表同士の結合処理の所要時間
縦軸は時間（ミリ秒）であり、小さい方が優れています。
左がPo stgreSQL 10 、右がPo stgreSQL 11 です。 縦軸の目盛りを合わせています。

6.12.3. 考察（ 結合）Po stgreSQL 11 ではパーティションワイズジョイン機能により明確に改善されています。
Po stgreSQL 10 では、パーティション表同士の結合は非パーティション表同士の結合より遅くなっていましたが、Po stgreSQL 11 では非パーティ
Page 31 of 41

PostgreSQL Enterprise Consortium
ション表同士の結合より速くなっています。
実行計画では以下の違いがあります。

Po stgreSQL 10 : Ap p n ed → Merge Jo in → 一括Partial Aggregate
日付条件が指定されていないテーブルはプルーニングが効きません。

Po stgreSQL 11 : パーティション毎のParallel Hash Jo in → パーティション毎のPartial Aggregate → Parallel
Ap p en d
一つのテーブルに日付条件が指定されていれば、他のテーブルもプルーニングが効きます。

●PostgreSQL 10=# EXPLAIN
SELECT count(*)
FROM lineorder_yyyymm l1,
lineorder2_yyyymm l2
WHERE l1.lo_orderdate = l2.lo_orderdateANDl1.lo_orderdate between 19920101 AND 19920331;
QUERY PLAN---------------------------------------------------------------------------------------------Finalize Aggregate (cost=794708399.23..794708399.24 rows=1 width=8)-> Gather (cost=794708399.02..794708399.23 rows=2 width=8)
Workers Planned: 2-> Partial Aggregate (cost=794707399.02..794707399.03 rows=1 width=8)-> Merge Join (cost=1767840.77..681471503.59 rows=45294358172 width=0)
Merge Cond: (l2.lo_orderdate = l1.lo_orderdate)-> Sort (cost=1648107.56..1673108.58 rows=10000407 width=7)
Sort Key: l2.lo_orderdate-> Append (cost=0.42..485382.47 rows=10000407 width=7)-> Parallel Index Only Scan using lineorder2_yyyymm_199201_...
-> Parallel Index Only Scan using lineorder2_yyyymm_199202_...
-> Parallel Index Only Scan using lineorder2_yyyymm_199203_...
～ 中略 ～-> Parallel Index Only Scan using lineorder2_yyyymm_199810_...
-> Parallel Index Only Scan using lineorder2_yyyymm_199811_...
-> Parallel Index Only Scan using lineorder2_yyyymm_199812_...

●PostgreSQL 11=# EXPLAIN
SELECT count(*)
FROM lineorder_yyyymm l1,
lineorder2_yyyymm l2
WHERE l1.lo_orderdate = l2.lo_orderdateANDl1.lo_orderdate between 19920101 AND 19920331;
QUERY PLAN---------------------------------------------------------------------------------------------Finalize Aggregate (cost=27222261.36..27222261.37 rows=1 width=8)-> Gather (cost=9140766.02..27222261.34 rows=6 width=8)
Workers Planned: 2-> Parallel Append (cost=9139766.02..27221260.74 rows=3 width=8)-> Partial Aggregate (cost=9396752.33..9396752.34 rows=1 width=8)-> Parallel Hash Join (cost=7879.52..6156318.15 rows=1296173675 ...
～ 中略 ～-> Partial Aggregate (cost=9139766.02..9139766.03 rows=1 width=8)-> Parallel Hash Join (cost=9084.77..5983755.36 rows=1262404264 ...
～ 中略 ～-> Partial Aggregate (cost=8684742.34..8684742.35 rows=1 width=8)-> Parallel Hash Join (cost=7340.90..5678423.17 rows=1202527670 ...

6.13. DELETEとTRUNCATE
DELETE およびTRU NCATE についてパーティション表の特性を確認します。
時系列データの保存期間切れデータはTRU NCATE できることがパーティション表の大きなメリットです。

Page 32 of 41

PostgreSQL Enterprise Consortium

TRU NCATE はVACU U M 負荷も気にする必要がないため、管理性に大きく寄与します。
以下の構成のテーブルを使用します。
表 6.20 使用するテーブル
構成

用途

非パーティションテーブル

DELETE

宣言的パーティション（年月）対象パーティションのDELETE とTRU NCATE

Po stgreSQL11 のみを対象としています。

6.13.1. 検証方法（ DELETEと TRUNCATE）
以下の3 ケースを実施
表 6.21 DELETE とTRU NCATE
ケ ース

条件指定

グラ フの凡例表記

ケース1

非パーティションテーブルに対して 3 ヶ月分のDELETE

DELETE(t)ケース2

年月パーティションテーブルに対して 3 ヶ月分のDELETE

DELETE(p 3)

ケース3

年月パーティションテーブルに対して 3 ヶ月分のTRU NCATETRU NCATE(p 3)●ケース1 (非パーティションテーブルに対して 3ヶ月分のDELETE）=# DELETE FROM lineorder WHERE lo_orderdate BETWEEN 19920101 AND 19920331●ケース2 (年月パーティションテーブルに対して 3ヶ月分のDELETE）=# DELETE FROM lineorder_yyyymm_199201;=# DELETE FROM lineorder_yyyymm_199202;=# DELETE FROM lineorder_yyyymm_199203;●ケース3 (年月パーティション表に対して 3ヶ月分のTRUNCATE）=# TRUNCATE lineorder_yyyymm_199201;=# TRUNCATE lineorder_yyyymm_199202;=# TRUNCATE lineorder_yyyymm_199203;

6.13.2. 結果（ DELETEと TRUNCATE）

3 ヶ月データにおけるDELETE およびTRU NCATE の所要時間
縦軸は時間（ミリ秒）であり、小さい方が優れています。
DELETE(p 3)およびTRU NCATE(p 3)は3 パーティションに対してシリアルに実行した時間の合計です。

6.13.3. 考察（ DELETEと TRUNCATE）
TRU NCATE は当然ながら圧倒的に高速です。

Page 33 of 41

PostgreSQL Enterprise Consortium

DELETE はこの後に VACCU M が発生することを考慮するとより大きな差と言えます。
TRU NCATE ができない場合でも、パーティションテーブルでは子テーブルを指定してのDELETE で改善が見込めます。
本検証では実施していませんが、INSERTとDELETE が同時に実行されるケースでも、それぞれ別パーティションとなることで改善が見込めます。

6.14. パーティショニング性能検証のまとめ
本性能検証では、主に以下の内容が確認できました。

6.14.1. 挿入処理
宣言的パーティションは継承によるパーティションの課題であった挿入処理(CO PY FRO M/INSERT)で大きな改善が確認できました。
特に CO PY FRO M では宣言的パーティションの優位が顕著です。

6.14.2. 索引走査とプル ー ニ ン グ
非パーティション表でも検索範囲が狭い範囲では、索引走査によりパーティション表と遜色ない結果となっています。
ただし検索範囲が一定割合を超える場合は全表走査に切り替わるため、パーティション表が優位となります。
パーティション表のプルーニングは検索範囲に依らず、安定的に機能します。

6.14.3. 適切なパー ティシ ョ ン 数
本検証におけるパーティション粒度（数）は年月(84)が最も効率的でした。
ただしパーティション数が数百のケースを検証できていないため、参考程度に留めてください。

6.14.4. パー ティシ ョ ン 数と実行計画
パーティション数が多い場合、パーティション選定の処理時間が増えますが、実行計画を立てる時間も増えます。
参考までに、全体の所要時間における実行計画を立てる時間の割合の例を示します。

所要時間における実行計画を立てる時間の割合
左が検索範囲3 日、右が検索範囲3 月です。
縦軸の単位はミリ秒です。
青色が実行計画を立てる時間、茶色が実行時間です。
3 日（左図）の年月日構成では、所要時間の殆どが実行計画を立てる時間です(91.2% )。
3 月（右図）の年月日構成では、実行計画を立てる時間は3 日と同じですが、実行時間が長くなるため割合は減少します(27.0% )。

6.14.5. PostgreSQL 11新機能
パラレルワーカによるパーティション走査の高速化

Po stgreSQL 11 ではパラレルワーカによるパーティション走査が改善されて高速化しています。
Po stgreSQL 11 では並列度を増加することでより高速化する余地があります。
パーティション選定の高速化
挿入処理(INSERT)では2,400 万件のINSERT文を実施したため、パーティション選定の高速化の成果が顕著に表れています。
パーティション・ワイズアグリゲート

Po stgreSQL 11 の新機能であるパーティションワイズアグリゲートは、集計処理を高速化します。
集計処理は日常的に実施されるため大いに活用が見込めます。
パラメータ en ab le_p artitio n w ise_aggregate= o n を設定することで機能します(デフォルトはo ff ）。

Page 34 of 41

PostgreSQL Enterprise Consortium
パーティション・ワイズジョイン

Po stgreSQL 11 の新機能であるパーティションワイズジョインは、同一レベルのパーティション表の結合処理を高速化します。
同一レベルのパーティション表の結合であるため、活用はある程度限られるかもしれません。
パラメータ en ab le_p artitio n w ise_jo in = o n を設定することで機能します(デフォルトはo ff ）。

6.14.6. 削除処理
削除処理（ DELETE/TRU NCATE)ではパーティション表の優位が確認できました。
パーティションの構成次第で、不要データをTRU NCATE で処理できます。

Page 35 of 41

PostgreSQL Enterprise Consortium

7. パーティションテーブルの Tips
7.1. パーティションが変更になるUPDATEPo stgreSQL 11 では、パーティションが変更になるU PDATE が可能になりました。
Po stgreSQL 10 までは、DELETE およびINSERTが必要でした。
(実行例) 年月日パーティションの日付を変更●PostgreSQL 10 ではエラーが発生=# UPDATE lineorder_yyyymmdd
SET
lo_orderdate = '19980102'
WHERE lo_orderdate = '19920101';
ERROR: new row for relation "lineorder_yyyymmdd_19920101" violates partition constraint●PostgreSQL 11 では正常終了=# UPDATE lineorder_yyyymmdd
SET
lo_orderdate = '19980102'
WHERE lo_orderdate = '19920101';
UPDATE 10228

7.2. プルーニング適用条件
パーティションプルーニングを行うには、W HERE 句の条件でパーティションキーが指定されている必要があります。
ただし以下のように W HERE 句の指定の仕方によってパーティションプルーニングが効かない場合があるため、注意が必要です。
インデックスが使用される指定方法と類似していますが、前方一致が効かないなど相違点もあります。
以下はレンジおよびリストの場合であり、ハッシュは完全一致のみプルーニングされます。
表 7.1 パーティションプルーニング可能な条件指定
指定方法

指定例

完全一致

p artitio n -key = 20190101

範囲指定

p artitio n -key BETWEEN 20190101 AN D 20190201
p artitio n -key IN (20190101, 20190102)
p artitio n -key > 20190101 AND p artitio n -key < 20190131
表 7.2 パーティションプルーニング不可能な条件指定

指定方法

指定例

備考

前方一致
中間一致
後方一致

p artitio n -key LIKE 'h o ge%'p artitio n -key LIKE '%h o ge%'p artitio n -key LIKE '%h o ge'

LIKE 演算子ではプルーニングできない

関数指定

TO _CHAR(p artitio n -key),'YYYYMMDD') = '20190101'

パーティションキー側に関数を指定している場合

7.3. パーティションテーブルおよびパーティションの一覧表示
パーティションテーブルの一覧を表示できるシステムカタログには以下があります。

p g_class テーブルp g_p artitio n ed_tab le テーブル
p g_in h erits テーブル

Page 36 of 41

PostgreSQL Enterprise Consortium
表 7.3 パーティション表の表示
システムカ タ ロ グ

内容
パーティションテーブルはrelkin d = 'p ' （宣言的パーティションテーブル）
子テーブルはrelkin d = 'r'
パーティションテーブルの索引は relkin d= 'I'(大文字）子テーブルの索引は relkin d= 'i'(普通）p g_classp g_p artitio n ed_tab le 宣言的パーティションニングのパーティションテーブルが対象
PARTSTRAT列でRANG E(r)/LIST(l)/HASH(h )が判別できる。
p g_in h erits

親子（継承）関係を示す。
パーティションテーブルとパーティションの一覧を表示できる。
継承を使用したパーティションニングおよび宣言的パーティションニングの両方に対応。

7.3.1. パー ティシ ョ ン テー ブル の 一覧表示
（実行例）-- パーティションテーブルの表示=# SELECT relname FROM pg_class WHERE relkind='p';relname------------------------lineorder_yyyy
lineorder_yyyymm
lineorder_yyyymmdd～以下略～-- パーティションテーブルおよび種類の表示=# SELECT partrelid::regclass,partstrat FROM pg_partitioned_table;
partrelid| partstrat-------------------------+----------lineorder_yyyy| r-- レンジlineorder_yyyymm| r
lineorder_yyyymmdd
| r
～以下略～

7.3.2. パー ティシ ョ ン の 一覧表示
（実行例）-- パーティションテーブルおよびパーティションの表示=# SELECT inhparent::regclass::name AS partition_table,
inhrelid::regclass::name AS partition
FROM pg_inherits;
partition_table|partition----------------------------+--------------------------------------lineorder_yyyy| lineorder_yyyy_1992
lineorder_yyyy| lineorder_yyyy_1993
lineorder_yyyy| lineorder_yyyy_1994～以下略～7.3.3. パー ティシ ョ ン 範囲の 表示
パーティション毎の範囲やリストを表示するには pg_get_expr関数 を使用します。
（実行例）

Page 37 of 41

PostgreSQL Enterprise Consortium=# SELECT i.inhparent::regclass::name AS partition_table,
i.inhrelid::regclass::name AS partition,
pg_get_expr(c.relpartbound, c.oid) AS bound
FROM pg_classc,pg_inherits i
WHERE c.oid = i.inhrelidAND
pg_get_expr(c.relpartbound, c.oid) IS NOT NULL;
partition_table |partition|
bound-----------------+---------------------+--------------------------------------------～レンジの例～

lineorder_yyyy
lineorder_yyyy
lineorder_yyyy| lineorder_yyyy_1992 | FOR VALUES FROM ('19920101') TO ('19930101')| lineorder_yyyy_1993 | FOR VALUES FROM ('19930101') TO ('19940101')| lineorder_yyyy_1994 | FOR VALUES FROM ('19940101') TO ('19950101')～リストの例～

lineorder_yyyy_1992_sub | lineorder_yyyy_1992_sub1 | FOR VALUES IN ('1-URGENT
lineorder_yyyy_1992_sub | lineorder_yyyy_1992_sub2 | FOR VALUES IN ('2-HIGH
lineorder_yyyy_1992_sub | lineorder_yyyy_1992_sub3 | FOR VALUES IN ('3-MEDIUM

7.4. パーティションテーブルの統計情報
以下の統計情報のシステムカタログではパーティション単位の情報が取得できます。
またパーティションテーブル全体の情報を取得するにはパーティションテーブル毎に集計します。

p g_stat_< all/u ser/sys> _tab les
p g_stat_< all/u ser/sys> _in dexes
p g_statio _< all/u ser/sys> _tab les
p g_statio _< all/u ser/sys> _in dexes
p g_stat_xact_< all/u ser/sys> _tab les
p g_in dexes
パーティションテーブルlin eo rder_yyyymmdd の統計情報の取得例を示します。
n _live_tu p 列およびn _dead_tu p 列のパーティションテーブル全体の値を取得します。
ANALYZE はパーティションにカスケードして実施されます。

=# ANALYZE lineorder_yyyymmdd;
ANALYZE=# SELECT sum(n_live_tup) AS n_live_tup,
sum(n_dead_tup) AS n_dead_tup
FROM pg_stat_all_tables
WHERE relname LIKE 'lineorder_yyyymmdd_%';n_live_tup | n_dead_tup------------+-----------23996670 |0

パーティション名がLIKE が指定できる場合は上記で構いませんが、以下のように p g_in h erits を組み合わせるのが確実です。
パーティションテーブル名を完全一致で指定できるためです。

=# SELECT sum(n_live_tup) AS n_live_tup,
sum(n_dead_tup) AS n_dead_tup
FROM pg_stat_all_tables
WHERE relname IN (SELECT inhrelid::regclass::name
FROM pg_inherits
WHERE inhparent::regclass::name = 'lineorder_yyyymmdd');n_live_tup | n_dead_tup------------+-----------23996670 |0Page 38 of 41

')
')
')

PostgreSQL Enterprise Consortium

7.5. パーティションテーブルを指定できないコマンド
Po stgreSQL 11 におけるコマンドまたは関数には、パーティションテーブル（親）を指定できないものがあります。
基本的にはメンテナンス系のコマンドまたは関数であるため、大きな問題はないものと考えられます。
以下に代表的なコマンドまたは関数を示します。

CO PY TO (ファイルに出力）
下記のように直接パーティションテーブルを指定するとエラーとなります。
HINTにあるように、"CO PY (SELECT * FRO M < パーティションテーブル> ) TO .." と指定することでご対応ください。
なおCO PY FRO M はパーティションテーブルを直接指摘可能です。本検証でも実施しています。

--パーティションテーブル名がemployee_rangeのパーティション表に対して COPY TO文を実行
postgres=# COPY employee_range TO '/tmp/employee.dat' WITH CSV;ERROR: cannot copy from partitioned table "employee_range"
HINT: Try the COPY (SELECT ...) TO variant.

p g_p rew arm エクステンション
本検証では以下の様に PL/p gSQL にて lin eo rder_yyyymmdd_< YYYYMMDD> パーティションのp g_p rew arm を7 年分実行しています。
頻繁なアクセスが予想される直近のパーティションのみを対象にしても一定の効果が期待できます。

DO $$DECLARE
part
text := 'lineorder_yyyymmdd_';s_day
timestamp(0) := '19920101';e_day
timestamp(0) := '19981231';
i_day
timestamp(0) := s_day;
BEGIN
WHILE i_day <= e_day LOOPPERFORM pg_prewarm(part || TO_CHAR(i_day,'YYYYMMDD'));
i_day := i_day + interval '1 day';
END LOOP;
END;$$ LANGUAGE PLPGSQL;

REINDEXREINDEXはインデックスを再構築します。INDEX/TAB LE/SCHEMA/DATAB ASE/SYSTEM の各単位で指定できます。
INDEX単位でパーティションテーブルのインデックスを指定した場合は、エラーが発生します。
TAB LE 単位でパーティションテーブルを指定した場合は、警告が発生して処理をスキップします。
CLU STER
CLU STER はインデックスに従ってテーブルをクラスタ化します。
親テーブルを指定するとエラーが発生します。

p agein sp ect エクステンション
p agein sp ect は低レベルなデータベースページの内容を調べることができる関数を提供します。
親テーブルを指定するとエラーが発生します。

Page 39 of 41

PostgreSQL Enterprise Consortium

8. まとめ8.1. 宣言的パーティショニングの実装
Po stgreSQL 1O で実装された宣言的パーティショニングでは、従来の継承を使用したパーティショニングに比較し、管理性および性能が大幅に向上し、導入のしきいが下がっています。

8.2. 宣言的パーティショニングの進化
Po stgreSQL 11 ではさらに進化しています。
性能検証では、以下の性能に関わるPo stgreSQL 11 の新機能について検証を実施し、確認ができました。
パラレルワーカによるパーティション走査の高速化
パーティション選定の高速化
パーティション・ワイズアグリゲート
パーティション・ワイズジョイン
宣言的パーティショニングは今後も進化を続けます。

Page 40 of 41

PostgreSQL Enterprise Consortium

9. 著者（企業・団体名順）
版
第1.0 版(2018 年度W G 3)

所属企業・ 団体名

部署名

氏名

株式会社アシスト

データベース技術本部 技術統括部

柘植 丈彦

株式会社アシスト

サービス事業部 サポートセンター

家島 拓也

株式会社アシスト北海道

技術部

沼田 梨佐

NTTテクノクロス株式会社

Io Tイノベーション事業部

原田 登志

Page 41 of 41