postgresql 10 新機能 @osc 2017 fukuoka
TRANSCRIPT
PostgreSQL 10 新機能オープンソースカンファレンス 2017 Fukuoka
2017.10.07
日本PostgreSQLユーザ会 花田茂
自己紹介
•花田 茂(Shigeru HANADA)•クラウドな会社でサポートエンジニア
•PostgreSQLの開発に参加�主に外部データラッパ機能
• SNS� Twitter: @s87� https://www.slideshare.net/babystarmonja/
そもそも「PostgreSQL」とは?
•読み方は「ポストグレスキューエル」�または「ポストグレス」「ポスグレ」
•オープンソースのRDBMS� https://www.postgresql.org
•開発主体が企業ではなくコミュニティ� PGDG: PostgreSQL Global Development Group
•PostgreSQLライセンス(BSD系)�改変可能、ソース提供不要
そもそも「PostgreSQL」とは?
•開発系の機能� SQL標準に準拠した構文のサポート
� 集計用途のウィンドウ関数なども
�効率的な実行計画� 各種スキャン、結合(Nested Loop、Merge Join、Hash Join)
�豊富なインデックス種別� B-Tree、Hash、GiST、SP-GiST、GIN、BRIN
�豊富なデータ型と演算子� JSON、幾何(図形)データ、IPアドレス、配列、範囲型
�豊富なストアドプロシージャ・ファンクション言語� PL/pgSQL、SQL、JavaScript(v8)、Python、etc.
そもそも「PostgreSQL」とは?
•運用管理系の機能�レプリケーション(同期・非同期)
� MySQLの用語でいう「準同期」レプリケーション
� 物理レプリケーション
� カスケードも可能
�リモートバックアップ� pg_basebackupでネットワーク越しに物理バックアップを取得
� PITR(Point in Time Recovery)� 任意のタイミングを指定してリカバリ可能
� GUIツール� pgAdmin3/pgAdmin4
そもそも「PostgreSQL」とは?
•アーキテクチャ的な特徴�プロセスモデル
� スレッドモデルと比較して接続確立が比較的重い
� pgpool-IIやアプリケーションサーバーでの接続プーリングをおすすめ
�追記型MVCC� 更新・削除時に古いバージョンに削除フラグを立てて残す
� VACUUMが必要、ただし現在はデフォルトで自動化
� OracleやMySQLは上書き型で、UNDO領域を持つ
� WALベースのストリーミングレプリケーション� 物理レプリケーションのためレプリケーションエラーは発生しづらい
� メジャーバージョンを跨げないのでローリングアップグレードできない
そもそも「PostgreSQL」とは?
•プラガブル(Pluggable)�関数
� SQL、PL/pgSQL、Tcl、Perl、Python、JavaScript(V8)、R、Etc.�外部データラッパ
� PostgreSQL、File、MySQL、Oracle、Redis、MongoDB、Twitter、Etc.�カスタムスキャン
� Pg-Strom (GPGPUを使ってデータを超並列処理)� http://strom.kaigai.gr.jp
� 手続き言語� 好きな言語で関数を書ける!
�インデックス
そもそも「PostgreSQL」とは?
•他のDBMSとの比較� PostgreSQLとMySQL、使うならどっち? データベース専門家が8つの視点で徹底比較!(エンジニアHub)� https://employment.en-japan.com/engineerhub/entry/2017/09/05/110000
�そーだいなるらくがき帳今こそ知りたい、2大OSSデータベースのMySQLとPostgreSQLの違いについて話をしてきた(そーだいなるらくがき帳)� http://soudai.hatenablog.com/entry/2017/05/27/173055
バージョンについて
•バージョン表記�従来は 「 9.6.5」のように三つの数字で表記
� 最初の二つがメジャーバージョン、新機能追加
� 最後の一つがマイナーバージョン、バグフィックスなど
�次バージョンから「10.1」のように二つの数字で表記� 最初がメジャーバージョン、新機能追加
� 最後がマイナーバージョン、バグフィックスなど
•概ね一年に一度メジャーバージョンリリース�現在の最新STABLEは10 (10/5リリースほやほや!)�一つ前は9.6.5
最近のバージョンの推移
• 9.5� UPSERTサポート
� INSERT ~ ON CONFLICT DO UPDATE ~� BRIN(Block Range Index)
� ブロック範囲でインデックスをはる、大規模テーブル向け機能
� Row-level Security� 列値とクエリ実行ユーザーなどにもとづいてアクセス権を設定
�同時実行性能の改善� ロック改善などで多CPUコア環境でよりスケール可能に
最近のバージョンの推移
• 9.6�パラレルクエリ
� スキャン、結合、集約を並列に実行
�マルチ同期レプリケーション� 複数のレプリカに同期レプリケーションが可能に
� FDW(Foreign Data Wrapper)機能強化� DATABASE LINKやリンクサーバーのような機能
� ソートや結合を外部データソースで実行可能に
最近のバージョンの推移• 10�パラレルクエリの改良
� B-Treeインデックススキャン、ビットマップスキャン、マージ結合、一部のサブクエリ
�ロジカルレプリケーション� 論理レプリケーションが可能に
�ネイティブパーティショニング� テーブル継承による擬似パーティショニングから構文サポートに
�マルチ同期レプリケーションでのQuorum Commit� N台に同期すればOK
�その他� ハッシュインデックスのWALサポート(クラッシュセーフ)� 複合列での統計情報のサポート
Major enhancements in PostgreSQL 10 include:•出版・購読型のロジカルレプリケーション
•宣言的テーブルパーティショニング
•パラレルクエリの改善
•全般的なパフォーマンス改善
• SCRAM-SHA-256ベースのより強固なパスワード認証
•監視と制御の改善
パラレルクエリ
パラレルクエリの概要
•WorkerとGather�パラレル度数に合わせてWorkerを起動して処理
�各Workerの出力をGatherしてまとめる
Gather
Worker Worker Worker
パラレルクエリ関連のGUC(1)•パラレル処理の制御� max_parallel_workers_per_gather
� Gatherごとの最大Worker数� max_parallel_workers
� インスタンス全体での最大Worker数� min_parallel_table_scan_size
� パラレルクエリを検討する最小テーブルデータ量
� min_parallel_index_scan_size� パラレルクエリを検討する最小インデックスデータ量
� force_parallel_mode� デバッグ用途などでパラレルクエリを強制
パラレルクエリ関連のGUC(2)•実行計画作成時のコスト計算など� parallel_setup_cost
� パラレルクエリでのWorker起動コスト
� parallel_tuple_cost� パラレルクエリでのタプル転送コスト
パラレルクエリの例
•標準ベンチマークツールのpgbenchを使用
•「支店ごとの預金残高の平均」を集計
postgres=# EXPLAIN SELECT bid, avg(abalance) FROM pgbench_accounts WHERE aid % 10 = 0 GROP BY bid ORDER BY bid;
QUERY PLAN------------------------------------------------------------------------------------------------------------Finalize GroupAggregate (cost=2286598.72..2288424.56 rows=1000 width=36)Group Key: bid-> Gather Merge (cost=2286598.72..2288402.06 rows=2000 width=36)
Workers Planned: 2-> Partial GroupAggregate (cost=2285598.69..2287171.19 rows=1000 width=36)
Group Key: bid-> Sort (cost=2285598.69..2286119.52 rows=208333 width=8)
Sort Key: bid-> Parallel Seq Scan on pgbench_accounts (cost=0.00..2264345.00 rows=208333 width=8)
Filter: ((aid % 10) = 0)(10 rows)
パラレルクエリの例 Finalize GroupAggregate
Group Key: bid-> Gather Merge
Workers Planned: 2-> Partial GroupAggregate
Group Key: bid-> Sort
Sort Key: bid-> Parallel Seq Scan on pgbench_accounts
Filter: ((aid % 10) = 0)
パラレルクエリの例 Finalize GroupAggregate
Group Key: bid-> Gather Merge
Workers Planned: 2-> Partial GroupAggregate
Group Key: bid-> Sort
Sort Key: bid-> Parallel Seq Scan on pgbench_accounts
Filter: ((aid % 10) = 0)
パラレルクエリの例 Finalize GroupAggregate
Group Key: bid-> Gather Merge
Workers Planned: 2-> Partial GroupAggregate
Group Key: bid-> Sort
Sort Key: bid-> Parallel Seq Scan on pgbench_accounts
Filter: ((aid % 10) = 0)
パラレルクエリの例 Finalize GroupAggregate
Group Key: bid-> Gather Merge
Workers Planned: 2-> Partial GroupAggregate
Group Key: bid-> Sort
Sort Key: bid-> Parallel Seq Scan on pgbench_accounts
Filter: ((aid % 10) = 0)
パラレルクエリの例 Finalize GroupAggregate
Group Key: bid-> Gather Merge
Workers Planned: 2-> Partial GroupAggregate
Group Key: bid-> Sort
Sort Key: bid-> Parallel Seq Scan on pgbench_accounts
Filter: ((aid % 10) = 0)
パラレルクエリの例 Finalize GroupAggregate
Group Key: bid-> Gather Merge
Workers Planned: 2-> Partial GroupAggregate
Group Key: bid-> Sort
Sort Key: bid-> Parallel Seq Scan on pgbench_accounts
Filter: ((aid % 10) = 0)
パラレルクエリの例 Finalize GroupAggregate
Group Key: bid-> Gather Merge
Workers Planned: 2-> Partial GroupAggregate
Group Key: bid-> Sort
Sort Key: bid-> Parallel Seq Scan on pgbench_accounts
Filter: ((aid % 10) = 0)
パラレルクエリの例
•大規模テーブル同士をPK(またはインデックスのある列)で結合
postgres=# EXPLAIN SELECT count(*) FROM pgbench_accounts a1 JOIN pgbench_accounts a2 ON a1.aid = a2.aid;QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------------------Finalize Aggregate (cost=5486220.02..5486220.03 rows=1 width=8)-> Gather (cost=5486219.81..5486220.02 rows=2 width=8)
Workers Planned: 2-> Partial Aggregate (cost=5485219.81..5485219.82 rows=1 width=8)
-> Merge Join (cost=1.14..5381053.14 rows=41666667 width=0)Merge Cond: (a1.aid = a2.aid
) -> Parallel Index Only Scan using pgbench_accounts_pkey on pgbench_accounts a1 (cost=0.57..2013443.23 rows=41666667 width=4)
-> Index Only Scan using pgbench_accounts_pkey on pgbench_accounts a2 (cost=0.57..2596776.57 rows=100000000 width=4)(8 rows)
パラレルクエリの今後
•APPEND(UNION)•COPY FROM•インデックス作成
•VACUUM• SERIALIZABLE分離レベル
宣言的パーティショニング
パーティショニングの概要
•パーティショニングとは�論理的には一つの大きなテーブルを物理的に分割すること
�分割基準は値リスト・範囲などが一般的
•効果�検索条件に応じて特定パーティションのみ処理することでパフォーマンス向上が望める
�パーティション単位で削除することで負荷を軽減(DELETEは遅い)
�あまり参照されないパーティションを遅いが安価なストレージに配置してコストを削減
これまで
•機能の組み合わせでパーティショニングを実現�「テーブル継承」で全パーティションのデータを集約
�「Constraint Exclusion(制約による排除)」でパーティションプルーニング(不要なパーティションの除外)
�「行トリガー」でレコードの配置を決定
•このため、パーティション管理が非常に煩雑�パーティション追加・削除時にトリガー実装変更が必要
宣言的パーティショニング•レンジとリストをサポート�レンジ: 年月、名称など�リスト: コード値など�パーティションキーには関数呼び出しなどの式も指定可能
� 「パーティションキーのための列」が不要になる
•親テーブルと子テーブル�パーティション基準を指定して親テーブルを作成したのちに、各パーティションの子テーブルを作成する
�インデックスは各子テーブルに作成→一つのサイズが小さくなり、頻繁にアクセスされるパーティションのインデックスがメモリに配置されやすくなる
9.6までの手順
•親表を作成
•パーティション追加時には�子表を作成
�子表にチェック制約を追加
�親表のトリガーに新規パーティション分の条件分岐を追加� 子表の名前とパーティションキー値を対応付けることでトリガー変更を避けられるがロジックが複雑化&判定処理コストが増加
10での手順
•親表を作成
•パーティション追加時には�子表をパーティションとして作成
10での具体的なDDL•親表を作成� CREATE TABLE parent(…) PARTITION BY [{RANGE|LIST} ({column|expression})];
•子表を作成� CREATE TABLE child_1 PARTITION OF parent FOR VALUES FROM ({minimum value|MINVALUE}) TO ({maximum value|MAXVALUE});� 下限は「以上」、上限は「未満」→上限=次の下限
� 制限なしの意味で「MINVALUE」や「MAXVALUE」も指定可能
� CREATE TABLE child_1 PARTITION OF parent FOR VALUES IN (value[ , …]);
具体的なDDL(リスト)/* まず親テーブルを作成 */CREATE TABLE sales_item (
id int NOT NULL,shop_id int NOT NULL,sales_date date NOT NULL,amount bigint,note text
) PARTITION BY LIST(shop_id);
/* 店舗ごとに子テーブルを作成 */CREATE TABLE sales_item_kyusyu
PARTITION OF sales_itemFOR VALUES IN (1, 11, 23,100);
具体的なDDL(レンジ)/* まず親テーブルを作成 */CREATE TABLE sales_item (
id int NOT NULL,shop_id int NOT NULL,sales_date date NOT NULL,amount bigint,note text
) PARTITION BY RANGE (sales_date);
/* 売上年月ごとに子テーブルを作成 */CREATE TABLE sales_item_201701
PARTITION OF sales_itemFOR VALUES FROM ('2017-01-01') TO ('2017-02-01');
作成されたテーブルpostgres=# ¥d+ sales_item
Table "public.sales_item"Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
------------+---------+-----------+----------+---------+----------+--------------+-------------id | integer | | | | plain | |shop_id | integer | | | | plain | |sales_date | date | | | | plain | |amount | bigint | | | | plain | |note | text | | | | extended | |
Partition key: RANGE (sales_date)Partitions: sales_item_201701 FOR VALUES FROM ('2017-01-01') TO ('2017-02-01'),
sales_item_201702 FOR VALUES FROM ('2017-02-01') TO ('2017-03-01'),sales_item_201703 FOR VALUES FROM ('2017-03-01') TO ('2017-04-01')
実行計画postgres=# EXPLAIN SELECT * FROM sales_item WHERE sales_date = '2017-02-15';
QUERY PLAN-------------------------------------------------------------------------Append (cost=0.00..22.75 rows=5 width=52)-> Seq Scan on sales_item_201702 (cost=0.00..22.75 rows=5 width=52)
Filter: (sales_date = '2017-02-15'::date)(3 rows)
postgres=# EXPLAIN SELECT * FROM sales_item WHERE sales_date < '2017-02-15';QUERY PLAN
---------------------------------------------------------------------------Append (cost=0.00..45.50 rows=680 width=52)-> Seq Scan on sales_item_201701 (cost=0.00..22.75 rows=340 width=52)
Filter: (sales_date < '2017-02-15'::date)-> Seq Scan on sales_item_201702 (cost=0.00..22.75 rows=340 width=52)
Filter: (sales_date < '2017-02-15'::date)(5 rows)
わかりやすいブログ
•PostgreSQL 10の宣言的パーティション� NTTテクノクロス様の技術ブログ「情報畑でつかまえて」
�著者は「ぬこ@横浜」さん(@nuko_yokohama)� https://www.ntt-tx.co.jp/column/postgresql_blog/20171005/
論理レプリケーション
従来のレプリケーションは?
•従来のストリーミングレプリケーションは物理レプリケーション
•データブロックに対する操作などを記録したWALを伝搬するため、レプリカでもブロックイメージが同一となる
•レプリケーション先は読み取り専用のため競合はなくレプリケーションエラーは起きにくい
物理レプリケーションの制限
•メジャーバージョンを統一する必要がある�バイナリフォーマットに依存するため
�ローリングアップグレードができない
•常に全体をレプリケーション�「集計用途で特定テーブルのみ必要」などのユースケースでも、全体を保持できるH/Wが必要
� 1 to Nの関係のみで、特定のインスタンスに情報を集約できない
これまでは、サードパーティのレプリケーションツールで対応する必要があった
論理レプリケーションの概要
•PublisherとSubscriber�レプリケーション元でPublish(変更の配布)
�レプリケーション先でSubscribe(変更の購読)
•レプリケーションスロット�各レプリケーション先ごとにレプリケーション元に作成
�レプリケーション状況を把握し、不要なWALのみ削除
論理レプリケーションの注意点
•レプリケーション先と更新が競合しうる
• INSERT ON CONFLICT では実際に発生した変更のみが伝搬する
•COPY FROMはINSERTとして伝搬する
•TRUNCATEとDDLは伝搬しない
PostgreSQL関連情報
情報源
• JPUG (https://www.postgresql.jp)•Let’s Postgres (https://lets.postgresql.jp)•ML (https://www.postgresql.jp/npo/mailinglist)• Slack (https://postgresql-hackers-jp.herokuapp.com/)
•Twitter @jpug_study
参考文献• PostgreSQL Documents
� https://www.postgresql.org/docs/10/static/runtime-config-query.html
• PostgreSQL 10がやってくる!(その5) ロジカルレプリケーション基本編� http://qiita.com/nuko_yokohama/items/af3bbd9acbd9723b6b95
• PostgreSQL 10 Beta1 新機能検証結果� http://h50146.www5.hpe.com/products/software/oe/linux/mainstream/s
upport/lcc/pdf/PostgreSQL_10_New_Features_ja_20170522-1.pdf
• PostgreSQL10徹底解説� https://www.slideshare.net/masahikosawada98/postgresql10
• 次期バージョンPostgreSQL 10 の 新機能とその後の方向性� https://www.sraoss.co.jp/event_seminar/2017/db_tech_show_case_oss_2
017.pdf
Any Questions?