内部で動くプロセスの役割を知る〜PostgreSQLのきほん〜

この記事では

  • PostgreSQLの内部で動くプロセスの役割とは??
  • なぜそれらのプロセスが必要なのか??

についてまとめました。


データベースのパフォーマンスで課題が発生した際、

本記事の内容を押さえておくと

原因を調査する際の切り分けがスムーズにできると思います。


PostgreSQLの内部で動くプロセス全体像

まずはプロセス構成の全体像を見てみましょう。

PostgreSQLのプロセス構造の全体像


マスタサーバプロセスが他の全てのプロセスの親プロセスとなり、

PostgreSQL起動時にバックグラウンドプロセスを、

接続要求時にバックエンドプロセスを

上の図のように子プロセスとして起動しています。


ではそれぞれのプロセスの役割と、

なぜその役割が必要なのか

みていきましょう。


各プロセスの役割とプロセスの必要性

ライタ

ライタの動作イメージ


ライタは共有バッファ内の更新されたページを

対応するデータファイルに書き出すのが役割です。


PostgreSQLを含むデータベースは

ディスクI/Oが性能のボトルネックになることが多く、

ディスクI/Oを減らすための工夫がされています。


また、

ディスクI/Oよりもメモリ上で読み書きする方が高速です。

しかし、データベースに保存されている全てのデータを

メモリ上で読み書きするのはメモリサイズが一般的には足りません。


そのため、

例えばテーブルの更新やインデックスの更新が要求された際、

ディスクではなくメモリ上で更新を行い、

一定時間経過や、共有バッファが一杯になったタイミングで

ライタがデータファイルに対して更新を行います。

これによってディスクI/Oを減らしてシステム全体のパフォーマンスを高めることができます。


WALライタ

WALライタの動作イメージ


WALライタの役割やその必要性も

ライタと同じでディスクI/Oを減らすことで

システム全体のパフォーマンス向上に貢献します。


そもそもWAL(Write Ahead Logging)とは

テーブルの更新などのトランザクションが開始されると、

データを更新する前に更新ログを先に書き込みます。


この更新ログをWALと呼び、

これはトランザクションの途中でシステムがクラッシュした際に、

クラッシュ直前のチェックポイント+WALで

クラッシュ直前の断面を再現するために必要です。


チェックポインタ

チェックポイントの動作イメージ


チェックポインタはメモリ上だけで更新された情報を

ディスクに書き込みます。(このタイミングがチェックポイント)


先ほど説明したようにディスクI/Oをできる限り減らしたり遅らせることで、

システム全体のパフォーマンス向上を行っていますが、


PostgreSQLがクラッシュした場合、

メモリ上での更新情報は壊れてしまうことがあります。

PostgreSQLがクラッシュしてメモリ上での更新情報が壊れても、

チェックポイントの断面での更新情報が全てディスクに保持されていれば、

クラッシュ直前のチェックポイントでディスクに保存された

データファイルとWALファイルから

クラッシュ直前にコミットされた断面を迅速に再現できます。

チェックポイント+WALでリカバリイメージ図


チェックポイントの頻度は適切に設定する必要があります。

頻繁が高すぎると

ディスクI/Oが増加してシステムのパフォーマンスが落ちます。

逆に頻度が低すぎると

システムクラッシュ時のリカバリに時間がかかることになります。


自動バキュームランチャと自動バキュームワーカ

自動バキュームランチャ・ワーカの動作イメージ


自動バキュームランチャは

各テーブルの挿入、更新、削除の回数や、不要領域の数などの

テーブルアクティビティ統計情報を監視してこれらが閾値を超えたら

自動バキュームワーカを起動します。


自動バキュームワーカは

不要領域を再利用できるようにし、

テーブルの各列のデータの偏り分布を収集して

列統計情報を更新します。


PostgreSQLではテーブルのレコードが更新されると、

データとしては更新前を不要領域として更新後の情報を登録する

追記型のアーキテクチャを採用しています。

不要領域を放置しておくと、

ディスクI/Oで目的のデータにアクセスするまでに

無駄なI/Oが発生したりします。


そのため、

不要領域を定期的に再利用可能な状態にしてやる必要があり、

その作業を自動バキュームランチャと自動バキュームワーカで行っています。

(この作業をバキュームと呼ぶ)


また、

統計情報には2種類があり、

まず1つ目のテーブルアクティビティ統計情報は

後述の統計情報コレクタが定期的に収集して、

この情報を参考に自動バキュームランチャが自動バキュームをいつ行うか判断します。

(pg_stat_user_tables や pg_stat_all_tablesといったシステムカタログのビューで参照できる)


2つ目の列統計情報は

クエリに対してどのようにデータにアクセスするのが

効率的かを判断するクエリプランナが利用します。

列統計情報が実態と乖離してしまうと

クエリプランナが効率的にデータアクセスするプランを導き出せません。

(pg_statsやpg_statisticといったカタログで参照できる)


統計情報コレクタ

統計情報コレクタ動作イメージ


統計情報コレクタは定期的に先ほど説明した

テーブルアクティビティ統計情報を収集してディスクに書き出します。


バックエンドプロセス

バックエンドプロセスの動作イメージ


クライアントから接続要求を受けるとマスタサーバプロセスから起動されるプロセスです。

接続要求が同時に複数あればその分プロセスが起動され、

上の図のようにプロセス毎にメモリ領域も確保されます。


メモリ領域の設定では、

同時アクセス数も考慮しながら設定するようにしましょう。


今回の内容は以上です。

現場で役立つデータベースの基礎知識という

まとめ記事を作ったので是非ご覧ください。

初めてデータベースを触る方に向けて〜新人プログラマー時代の自分に伝えたいこと〜


参考文献

第2章 アーキテクチャの基本

[改訂3版]内部構造から学ぶPostgreSQL―設計・運用計画の鉄則

第4章 処理/制御の基本

[改訂3版]内部構造から学ぶPostgreSQL―設計・運用計画の鉄則

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください