サーバプロセスの役割
マスタサーバプロセス
- いろいろfork()する人
postgres@b612ca6ed5fc:/$ ps -ef | grep postgres
postgres 1 0 0 Jan29 ? 00:00:01 postgres
postgres 57 1 0 Jan29 ? 00:00:00 postgres: checkpointer
postgres 58 1 0 Jan29 ? 00:00:01 postgres: background writer
postgres 59 1 0 Jan29 ? 00:00:01 postgres: walwriter
postgres 61 1 0 Jan29 ? 00:00:01 postgres: stats collector
postgres 62 1 0 Jan29 ? 00:00:00 postgres: logical replication launcher
postgres 370 356 0 Jan29 pts/0 00:00:00 /usr/lib/postgresql/12/bin/psql
postgres 378 1 0 Jan29 ? 00:00:00 postgres: postgres postgres [local] idle
postgres 1224 1 0 Jan29 ? 00:00:00 postgres: autovacuum launcher
- pid 1
postgres
がマスタサーバプロセス - 他のは子
ライタプロセス
WALライタプロセス
チェックポインタ
自動バキュームランチャと自動バキュームワーカ
統計情報コレクタ
- autovacuumは統計情報に依存している
- ので、
track_counts
がoffならautovacuum
もoffにしないといけない autovacuum
をonにするときはtack_counts
もonにする必要がある
postgresql.conf
#autovacuum = on # Enable autovacuum subprocess? 'on'
# requires track_counts to also be on.
- 設定変更タイミングとか
postgres=# SELECT name,setting,context FROM pg_settings WHERE name=ANY(array['track_counts', 'autovacuum']);
name | setting | context
--------------+---------+-----------
autovacuum | on | sighup
track_counts | on | superuser
(2 rows)
- いずれもサーバ起動中に設定できる
track_counts
はスーパユーザのSET
でoffにできる- が、結局
autovacuum
もALTER SYSTEM
か何かでoffにしてreloadする必要がある
バックエンドプロセス
Column: バックグラウンドワーカプロセス
- 公式
-
ユーザ独自のワーカプロセスをPostgreSQLに組み込めるやつ
- PostgreSQLサーバと同じライフタイム
- 監視とかに
クライアントとサーバの接続/通信
問い合わせの実行
パーサ
-
字句解析
- トークン・識別子をバラすだけ
-
構文解析
- セマンティクス
- ここまででエラーが出たら「syntax error」
postgres=# SELECT *;
ERROR: SELECT * with no tables specified is not valid
LINE 1: SELECT *;
^
-
実在するかの確認
- テーブル名
- 列名
- etc.
postgres=# SELECT * FROM tbl;
ERROR: relation "tbl" does not exist
LINE 1: SELECT * FROM tbl;
^
リライタ
- 公式
- viewに対してupdateをかけようとしたらtableへのupdateに読み替える的なやつ
プランナ/オプティマイザ
個々のテーブルに対するアクセス方法の選択
- まずSeqScanが候補
- 適宜IndexScanとかBitmapScanとかも候補に
結合方法の選択
- 公式
-
入れ子ループ
- 実装は簡単
-
実行時間がかさむ
- ただし、右側のrelationがインデックススキャンだと速い
-
merge join
-
join前に左右のrelationがソート済ならば、走査が1回ずつだけで済むやつ
- 【補】merge sortみたいなかんじ
- 明示的にsortするか、ソート済の(B-treeとか)indexを使うか
-
-
hash join
- 右のrelationに対してハッシュテーブルを作って、左のrelationでルックアップするやつ
GEQO
- 公式/GEQO
- GEQO: Genetic Query Optimization
-
クエリ最適化は巡回セールスマン問題
- 複数のrelationをjoinするような場合、どの順番で・どの戦略でjoinをするか
- relation数が
geqo_threshold
以下ならほぼ全て網羅して最適な実行計画を探しに行く - 超えたらGEQOに切り替わる
postgres=# SELECT name,setting,context FROM pg_settings WHERE name SIMILAR TO 'geqo%';
name | setting | context
---------------------+---------+---------
geqo | on | user
geqo_effort | 5 | user
geqo_generations | 0 | user
geqo_pool_size | 0 | user
geqo_seed | 0 | user
geqo_selection_bias | 2 | user
geqo_threshold | 12 | user
(7 rows)
エグゼキュータ
- 公式
- DMLを実行する人
SQLの種別による動作
-
DDL,DCLは
-
プランナ素通り
- 実行計画も何もない
-
エグゼキュータ素通り
- 代わりに、対応する個々のコマンドを実行
-
トランザクション
トランザクションの特性
- ACID
- いつもの
トランザクションの制御
- DCL
トランザクションの分離レベル
- 公式
- いつもの
-
PostgreSQL特有の要素
-
READ UNCOMITTEDはREAD COMMITTED扱い
- ダーティリード発生しない
-
REPEATABLE READ
- V9.0以前はSERIALIZABLE扱いだったらしい
-
-
高ければいいというわけではない
- 分離レベルが高いと、直列化に失敗する可能性が出てくる
- 失敗したトランザクションの再実行などを別途考える必要が出てくる
postgres=# show transaction_isolation;
transaction_isolation
-----------------------
serializable
(1 row)
postgres=# select * from tbl;
col
-----
1
(1 row)
...
(他トランザクションによる更新・commit)
...
postgres=# update tbl set col=col+1;
ERROR: could not serialize access due to concurrent update
- このトランザクションがrollbackしたところで他トランザクションでcommitした変更はrollbackできないので直列化失敗する
- ↑のものはrepeatable readで発生するやつ
ロック
- 公式
-
トランザクションからの同時実行を確実にするため、明示的なロックを獲得できる
- 行
- テーブル
Column: 勧告的ロック
- advisory lock
- 公式
- アプリケーション固有のロックを定義できる
-
ビジネストランザクション(long transaction)のための悲観ロック等を実装するときに使える
-
フラグカラムとか使うより良い
- 高速
- テーブル太らない
- DBセッション終了時に自動的にクリーンアップされる
-
同時実行制御
- 公式
-
MVCC: Multi Version Concurrency Control を追記型アーキテクチャで実現
- ロックとは異なる路線の同時実行制御
-
ロックと比較してパフォーマンスにすぐれる
- read/writeが互いにブロックしない