More Related Content Similar to PostgreSQLのパラレル化に向けた取り組み@第30回(仮名)PostgreSQL勉強会 (20) More from Shigeru Hanada (12) PostgreSQLのパラレル化に向けた取り組み@第30回(仮名)PostgreSQL勉強会2. Who am I?
• 氏名:花田茂
• 所属:株式会社メトロシステムズ
• 連絡:@s87
• 経歴:
• PostgreSQLは7.4から
• 周辺ツール開発(pg_bulkload/pg_rman/pg_lesslog/Etc.)
• 最近は外部テーブル関連で本体開発
• 勉強会やOCSなどで講演
2
4. パラレル化って?
• definition of Parallel
• (of lines, planes, surfaces, or objects) side by side
and having the same distance continuously between
them: parallel lines never meet | the road runs parallel
to the Ottawa River.
• definition of Concurrent
• existing, happening, or done at the same time: there
are three concurrent art fairs around the city.
出典:アメリカ英英辞典 on OS X Mavericks
4
8. どのあたりが難しいのか?
• 対象の決定
• どの処理を高速化するか?
• 問題の分割
• どの部分をパラレルに分けるか?
• 動作の協調
• 処理主体(=プロセス)をどのように起動するか?
• どうやって、各自が何をすべきか知るか?
• 情報の受け渡し
• 入力・出力をどのように受け渡すか?
8
9. 対象の決定
• 性能改善の基本は「ボトルネック解消」
• ボトルネック以外を速くしても効果は薄い
• 「クリティカルパス」を明確に
• 例)データロードの場合
• 最大テーブルのロード
• 例)PostgreSQLのクエリ
• SQLパース+プラン生成+最大テーブルのスキャン
9
11. 対象の決定
• PostgreSQLでいうと?
• クエリ実行の要素
• プラン生成
• テーブルスキャン
• 結合
• ソート
• Etc.
• クエリ実行要素間
• 結合の片側をソート中にもう片方をスキャン、など
11
12. 対象の決定
• PostgreSQLでいうと?
• その他
• WAL書き込み
• チェックポイント
• テーブルメンテナンス
• VACUUM、ANALYZE、REINDEX
• ALTER TABLE
• バックアップ取得
12
13. 問題の分割
• どう分割したら早くなるか?
• まじめに考えると論文書けるレベルの問題がてんこ盛り
• スーパーコンピュータの超並列処理はここを頑張ってる?
• PostgreSQLの中の人たちの腕の見せ所
例題:100人分のカレーを作る
13
14. 問題の分割
• カレーの調理手順
• 米を研ぐ
• 米を炊く
• 肉を切る
• 肉を炒める
• 野菜を切る
• 野菜を炒める
14
!
• 鍋に入れる
• 煮込む
• カレールーを入れる
• 皿にご飯を盛る
• 皿にカレーを盛る
• 配膳
15. 問題の分割
野菜を切る
15
肉を切る
野菜を炒める肉を炒める
鍋に入れる
米を研ぐ
米を炊く
煮込む
カレールーを入れる
皿にご飯を盛る皿にカレーを盛る配膳
16. 問題の分割
Seq Scan
16
Seq Scan
Sort Sort
Merge Join
Index Scan
Aggregate
Sort
Aggregate
Limit Append Limit
18. 動作の協調
• PostgreSQLはプロセスベース
• セッション障害がインスタンス全体に波及しない
• オーバーヘッドはスレッドより大きい
• インスタンスに所属するプロセスの一覧を管理
• PGPROCという構造体の配列を共有メモリ上に配置
• postmaster(≒インスタンス)起動時に初期化
• PGPROCは同期機構のラッチを持つ
18
19. 動作の協調
• プロセス間のやりとり
• 共有メモリ
• シグナル
• プロセス間の同期
• スピンロック:超短期間(数十命令程度)用
• 軽量ロック:共有メモリ資源の保護
• ラッチ:複数プロセスからセットできる真偽値
19
20. 動作の協調
• MVCC
• 概要
• Multi Version Concurrency Control
• 更新時に古いバージョンを残したまま新しいバージョン
を追加することで、特定タプルの可視性を効率的に判断
する仕組み
• 判断材料
• 自TXのID(XID)
• スナップショット(アクティブなTXのリスト)
• タプルの作成/削除TX(xmin/xmax/cmin/cmax)
20
21. 情報の受け渡し
• 基本的には共有メモリを使用
• 既存の仕組みをそのまま共有メモリに展開すれば…と思い
ますが、一筋縄(ry
• PostgreSQLはヒープメモリの管理に独自アロケータを
使用
• 細かく確保した後に「コンテキスト」という単位で一括
解放が可能
• 共有メモリには非対応
• 既存ルーチンで扱うには「ヒープ→共有→ヒープ」というメ
モリコピーが必要
21
23. パラレル化への取り組み
• 9.2
• スナップショットエクスポート
• 9.3
• pg_dumpの--jobsオプションサポート
• pg_upgradeの--jobsオプションサポート
23
24. パラレル化への取り組み
• 9.4(予定)
• 動的バックグラウンドワーカー
• Allow background worker processes to be
dynamically registered, started and terminated
(Robert Haas)
• 動的共有メモリ
• Allow dynamic allocation of shared memory
segments (Robert Haas, Amit Kapila)
• 共有メッセージキュー
• Add single-reader, single-writer, lightweight shared
message queue (Robert Haas)
24
25. パラレル化への取り組み
• 9.5(予定)
• On partitioning (Alvaro Herrera)
• 1st class objectとしてのパーティション
• 議論/開発継続中
• Introducing coarse grain parallelism by
postgres_fdw(Kyotaro Horiguchi)
• postgres_fdwでリモートクエリを非同期実行して待機
時間を節約
• 設計見直しが必要
25
26. スナップショットの共有
• pg_export_snapshot()関数
• 現在のトランザクションのスナップショットを$PGDATA/
pg_snapshotsに書き出すし、スナップショットIDを返す
• ファイル名=スナップショットID
• SET TRANSACTION SNAPSHOT ‘スナップ
ショットID’;
• 指定したIDのスナップショットを現在のトランザクション
で使用する
26
27. 動的バックグラウンドワーカー
• 概要
• 9.3で導入されたカスタムバックグラウンドワーカーの拡張
• 9.3ではインスタンス起動時にのみ起動できたが、9.4から
は、バックエンドからのAPI呼び出しで任意のタイミングで
起動可能
• 動的に起動したバックグラウンドワーカーの終了は
SIGUSR1で通知可能
• 起動数はmax_worker_processesで制御可能
• つまり…
• クエリ内容に応じて特定処理のバックグラウンドワーカー
を起動し、その終了を起動したバックエンド側で検知可能
27
28. 動的バックグラウンドワーカー
• API(バックエンド用)
• RegisterDynamicBackgroundWorker()
• バックエンドから動的BGWorkerを登録
• WaitForBackgroundWorkerStartup()
• 動的BGWorkerの起動を待機
• GetBackgroundWorkerPid()
• BGWorkerのPIDと状態を取得
• TerminateBackgroundWorker()
• PostmasterにBGWorkerの停止を依頼
28
29. 動的バックグラウンドワーカー
• API(BGWorker用)
• BackgroundWorkerInitializeConnection()
• ローカルデータベースに接続
• BackgroundWorkerUnblockSignals()
• BGWorkerプロセスへのシグナルブロックを解除
29
30. 共有メッセージキュー
• 概要
• 共有メモリ上に配置したプロセス間メッセージキュー
• 書き込み一人、読み込み一人の制限
• 書き込み/読み込みはロックフリー
• 読み書きはそれぞれPGPROCにエントリのあるプロセス
• 読みと書きの間はプロセスラッチで同期
• メッセージ長は任意
• キューは固定長でリングバッファ構造
30
31. 共有メッセージキュー
• API
• shm_mq_create()
• メッセージキューを生成
• shm_mq_set_receiver()/shm_mq_set_sender()
• 読み出し/書き込みプロセスを設定
• shm_mq_get_receiver()/shm_mq_get_sender()
• 読み出し/書き込みプロセスのPGPROCを取得
31
32. 共有メッセージキュー
• API
• shm_mq_attach()
• メッセージキューにアタッチしてハンドルを取得
• shm_mq_wait_for_attach()
• メッセージキューへのアタッチを待機
• shm_mq_detach()
• メッセージキューからデタッチ
32
33. 共有メッセージキュー
• API
• shm_mq_send()/shm_mq_receive()
• 可変長のメッセージを書き込む/読み出す
• ラッチでキューの空き/メッセージの到着を待機すること
も可能
33
36. スキャンの分割
ワーカーが
スキャン
36
ページ1
ページ2
ページ3
ページ4
ページ5
ページ6
ページ7
ページ8
ワーカー
ワーカー
バック
エンド
起動
起動
キュー経由で
結果を渡す
39. 集約の分割
• 概要
• ある結果セットの集約を複数プロセスで分担
• MAX()/MIN()やCOUNT()は多段集約が容易
• AVG()などはやや困難?
• 課題点
• 入力の分配
• 結果のとりまとめ
39
41. データロードの分割
• 概要
• バルクINSERTやCOPYを複数プロセスで分担
• 文字列→内部表現変換もパラレル化できると効果大
• 複数セッションでのINSERT/COPYと異なり1トランザ
クションで完結
• 課題点
• 追加先の衝突回避
• WALバッファのボトルネック化
41
43. I/OとCPUの分割
• 概要
• I/O待ちってもったいないよね?
• その間にCPU使う処理できるんじゃない?
• スキャン開始時にfadvise()などでread ahead
• postgres_fdwなどで非同期クエリ
• 課題点
• 先読み(投機的実行)はパイプライニングと相性が悪い?
• effective_io_concurrencyで十分?
• スピンドル数に基づいて同時I/O発行数を制御
43
44. CPU処理の分割
• 概要
• スキャン結果のフィルタリング(WHERE句適用)などは
CPU処理
• 対象行数が多い場合はCPUでの並列処理にも限界
• GPUでSIMDしちゃえば?
• 課題点
• 任意のコードをGPU側でコンパイル・実行する機能が必要
• pg_stromが開発中
44
46. 残っている課題
• リソース制御
• プロセス数やメモリ量、CPU使用率といったリソースを核
処理がどこまで使用してよいか?をクラスタ全体よりも細
かい粒度で制御する仕組みが必要
• これがないと、リソース枯渇でシステムダウンも
• work_memなども意味を変える必要あり?
46