Env
- PostgreSQL 9.6
client, server間の接続〜問い合わせ処理
- PostgreSQLへuser/passでのrequestを受信し、pg_hba.confで接続可否を判断
- (認証処理)
- 認証成功
- backend process生成
- clientがserverとの接続を確立
client側で発行したqueryがpostgres processへ渡る際に以下の手続きが発生する。
- parse (pg_parse_query)
- parserが文字列のqueryをraw parse treeへparseする ( PostgreSQL Source Code: src/include/nodes/parsenodes.h Source File )
- 字句・構文解析
- analyzeと書き換え (pg_analyze_and_rewrite)
- raw parse treeを分析し, 最適化を図る.
- plan
- execute
process architecture
- client request -> postgres process生成, fork -> processがSQL文を解析, 処理
- その他, background processがshared_buffer(PostgreSQL全体で利用する共有memory cache), WAL bufferの変更をHDDに書き込んだり, vacuum処理を行っている。
master server process (parent process)
- clientからの接続を受け, 対応するprocessをforkして起動する。
(background) writer process
- shared_bufferの更新pageをHDDのdata fileのblockに同期的に書き出す。
WAL (Write Ahead Logging) writer process
- WAL bufferの確認を行い, 未書き込みのWALをHDDに同期的に書き出す。
Checkpointer process
- checkpointを行い, shared_bufferの変更をHDDに同期的に書き込む。
- checkpointとは, 全てのdirty pageをdata fileへ書き出し, checkpoint recordがlog fileに出力された状態。
- checkpoint処理は全dirty pageをdiskに書き込む為、I/O負荷が高い傾向にある。
- checkpoint処理が頻発すると性能劣化にも繋がるが、recovery速度もその分早くなる。適切な設定をされたい。
- PostgreSQLではshared bufferをdisk cacheとして使用している為データ更新はshared buffer上で行われ直ぐにHDDに書き込まれるわけではない。
- HDDへ未だ書き込んでないpageのことをdirty pageと呼ぶ。
- PostgreSQL clash時にrecovery処理の起点を示すポイント。
Autovacuum launcher & Autovacuum worker process
- autovacuumの制御, 実行process。
- autovacuum用worker process起動をpostgresへ依頼する。
- workerはtableに対し自動的にvacuumとanalyzeを実行する。
- vacuumは更新や削除で発生したdata file, index内の不要領域を再利用可能にする。
- 実行前に対象tableに大量にupdateがあったかを統計情報を参照して検査 (analyze) する。
- pg_statistic system catalogを更新する。
統計情報 collector process
- DBの稼働統計情報(pg_stat_activity[database, all_tables])の収集を一定間隔で行う。
- 収集された情報はautovacuum worker等で利用される。
backend process
- clientからのrequestを受け付けた際に生成される。
- query, 結果の送受信を本processとclientでやり取りする。
- queryは本processで実行される。
parallel worker process
- parallel queryの実行時にbackend processから生成される.
後は, log writerとかarchiver等.
Memory architecture
- PostgreSQLでは, PostgreSQL server process全体で共有するshared_memoryとbackend processが確保するprocess memoryに大別される.
- PostgreSQL起動時, postgres process毎に
work_mem
,temp_buffers
,maintenence_work_mem
の領域を確保する. - shared memoryは
shared_buffers
,WAL buffer
,C(ommit)LOG,
free space map,
visibility map,
system catalog(postgres processにもコピーを保持)` の領域を確保する. - postgres process memory <-> shared memory <-> database cluster
shared_memory
shared_memoryはbackground processとbackend process全てから参照, 更新される領域.サーバ起動時にOSのsystem callから予約済となる.
PostgreSQL起動時にshared_bufferとLinuxのkernel parameterであるshmmaxを比較しshared_bufferが大きい場合エラーとなる.
shared_memoryは以下の領域に分割されている.
- shared buffers
- tableやindexデータを読み込みcacheし, CRUD操作を行う領域.
- WAL(Write Ahead Logging) buffer
- diskに未書き込みのtransaction log: WAL log(transaction log)のcache(buffering用)領域.
- C(ommit)Log
- transactionの状態を保存.
- Free Space Map (FSM)
- table上の空き領域(block毎の空き領域)情報.
- VACUUM処理の度transactionから非参照の行を探し空き領域としてdatabase clusterに保存され, 再起動時に読み込まれる.追加, 更新時に空き領域mapを確認, 再利用可能な領域に新しい行を挿入する.
- Visibility Map (VM)
- VACUUM処理高速化(処理が必要なpageか本mapで判断)やindex only scan(高速な検索方式)で利用される.
- tableのblock毎に全transactionから可視かどうかを保持している(1page/1bit).
- Visibility map書き換えタイミングは各種更新処理, VACUUM処理時.
process memory
- backend process毎の作業用領域.
work_mem
- Query実行時のsort, table join, hash table操作に利用される領域.
- sort, table join, hash table操作は作業メモリを適切に設定すると性能向上 (高速化) が期待出来る.
- session毎に設定が可能.
- memoryを要するsessionで, 都度大きな値を設定することが望ましい.
- 1つのqueryの中で上記操作が複数回実行される場合, 処理毎に設定領域が確保される.
- 例えば1つのquery (1回の問い合わせ) あたりではなく, Query中のsort処理のたびにwork_memの値のmemoryを消費する.
- その為, たくさんのbackend processが起動中にwork_memの値が大きいとシステム全体のmemoryが逼迫する.
- 1つのqueryで多数のtableをjoinする場合, work_memにx sort処理の回数分のmemoryが1queryで必要となる.
- sort処理は
order by
,distinct
,merge
結合で行われる. - 最大でwork_mem*max_connections+α消費する
maintenance_work_mem
- DB maintenanceの (保守) 操作で使われるmemoryの最大容量.
- vacuum
- create index
- alter table add foreign key
work_mem < maintenance_work_mem
とすることでmaintenance時間の短縮に繋がる.
catalog cache
postgres processへ頻繁にアクセスするsystem catalog(RDBMSがスキーマメタデータや内部的な情報を格納するtable)は, shared_bufferと合わせpostgres processにもコピーを保存している.これをcatalog cacheと言う.
temp_buffer
- 一時tableへのアクセスで利用される, backend process毎に生成されるmemory領域.
- 一時tableはcreatetemplate文で作成可能.
- applicationのパフォーマンスが悪くなる原因に
temp_data write
(write temporary table) が発生している場合がある.- その場合は (work_memを超えたらtemp tableを使うようになる為) query実行前にwork_memを大きくする必要がある.