18
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

書籍「改訂新版-内部構造から学ぶPostgreSQL-設計・運用計画の鉄則」のまとめ - 理論編

Posted at

はじめに

ここ最近、環境構築や障害調査、他RDBへの移行といった作業を行う中で、データベース内部の仕組みについて一度じっくりと学ぶ必要があるなと感じました。
色々とネットで調べたところ、PostgreSQLに関しては
[改訂新版]内部構造から学ぶPostgreSQL 設計・運用計画の鉄則
が良さそうだったので、この書籍を読んで学んだことをいくつかピックアップし自分なりにまとめます。
※あくまで個人の理解なので誤りがある可能性があります。ご了承ください。

基本的なアーキテクチャ

pg_architecture.png

プロセス

PostgreSQLではマルチプロセスモデルを採用。
プロセスは大きく分けてマスタサーバプロセス、バックグラウンドプロセス、バックエンドプロセスが存在する。

  • PostgreSQL起動時にマスタサーバプロセスが生成される
  • 生成されたマスタサーバプロセスが各制御用プロセス(バックグラウンドプロセス)をフォークする
  • クライアントからの接続要求時には、まずマスタサーバプロセスがリクエストを受け付けて、バックエンドプロセスをフォークし、以降、クライアントとバックエンドプロセスがやり取りする
  • つまりクライアントの数だけバックエンドプロセスが生成される

メモリ

共有メモリ

共有メモリとはすべてのプロセスで共有する領域。
大きく分けて共有バッファとWALバッファが存在する。

共有バッファ

  • テーブルやインデックスの情報をキャッシュする領域
  • キャッシュすることでテーブル情報などが格納されてるデータファイルに直接アクセスしないで済む(I/Oが発生しない)
  • 初回アクセス時にテーブルやインデックスの情報をキャッシュしておいて、2回目以降はキャッシュを参照する
  • UPDATEなどの更新処理が発生した際は、キャッシュしている共有バッファのデータが更新され、後からデータファイルに更新情報が反映される

WALバッファ

  • WAL(ログ先行書き込み:Write Ahead Logging)と呼ばれるPostgreSQLに対する更新情報をキャッシュする領域
  • UPDATEなどの更新処理が発生した際は、更新した内容が先にWALバッファに書き込まれる

空き領域マップ

テーブル上の利用可能な領域を指し示す領域

可視性マップ

テーブルのデータが参照できるか否かを管理する情報を扱う領域

プロセスメモリ

バックエンドプロセスから利用される領域で、バックエンドプロセスごとに存在する

作業メモリ

問い合わせ時のソートやハッシュテーブルの操作に使用する領域

メンテナンス用作業メモリ

バキュームやインデックスの作成など、データベースメンテナンスの操作で使用する領域

一時バッファ

CREATE TEMP TABLE で作成される一時テーブルにアクセスする際に使用する領域

ファイル

データファイル

pg_datafile.png

データファイルには、テーブルごとの実データを管理するテーブルファイルと、インデックスの情報を管理するインデックスファイルが存在する。

  • 8192バイトの「ページ」単位で構成され最大1Gバイト
  • 1Gバイトを超えると「ファイルノード番号.連番」の命名規則に則って分割管理される
  • ライタプロセスやチェックポインタによって共有バッファのデータが書き込まれる

WALファイル

pg_walfile.png

WALファイルにはPostgreSQLに対する更新情報が記録されていて、この情報を用いてレプリケーションやリカバリを行う

  • 更新内容が書かれている「WALレコード」単位で構成され最大16Mバイト
  • WALレコードにはLSN(Log Sequence Number)とよばれる番号が振られている
  • max_wal_size の値によりファイルの総数が決まり、ファイルの総数に達すると、古いファイルから上書かれていく
  • 上書きによるWALの消失を防ぐために、WALアーカイブファイルとして残すこともできる
  • WALライタプロセスによってWALバッファのデータが書き込まれる

プロセス・メモリ・ファイルの関係

WALバッファ -> WALライタプロセス -> WALファイル

  • UPDATEなどの更新処理が発生した場合、まずWALバッファに更新情報が書き込まれる
  • COMMITを行った契機でWALバッファの情報がWALライタプロセスによってWALファイルに書き込まれる

共有バッファ -> ライタプロセス(or チェックポインタ) -> テーブルファイル・インデックスファイル

  • UPDATEなどの更新処理が発生した場合、まず共有バッファ上のデータが更新される
  • この更新された情報(ダーティーページ)はすぐにはデータファイルには反映されない
    • 随時データファイルへの書き込みを行うとI/Oが頻発してパフォーマンス上よろしくない
  • ダーティーページのデータファイルへの書き込みはライタプロセスおよびチェックポインタで行われる
    • 書き込み時はI/Oが発生するので、問い合わせが遅くなる原因にもなる

ストリーミングレプリケーション

pg_streamingreplication.png

ストリーミングレプリケーションとは、マスタースレーブ構成において、プライマリの更新内容ごとに(WALレコードごとに)スタンバイへと送る機能

  • スタンバイでは送られてきたWALを実行することで、プライマリと同じ状態を保つことができる。
  • 実際にはプライマリ側のwalsenderプロセスと、スタンバイ側のwalreceiverプロセスでやりとりを行う

バックアップ・リカバリ

pg_backup.png

障害が発生した際に、障害前の状態に戻すために必要となるファイル群をとっておき(=バックアップ)、
それらのファイル群をリストアすることで障害前の状態に戻すこと(=リカバリ)

必要なファイル群は以下のとおり

  • ベースバックアップ(テーブルやインデックスの情報)
  • アーカイブWALファイル
  • 直前のWALファイル

VACUUMについて

追記型アーキテクチャ

PostgreSQLでは追記型アーキテクチャを採用している。
例えばある行に対してUPDATE文を実行した場合、既存の行の領域は不要領域として残したまま、更新後の行の領域が新たに追加される。
そのためUPDATE処理を行っていくと、その分だけ物理データが増えていく。

VACUUMとは

バキュームとは更新や削除によって発生したデータファイル内の不要領域をクリアし、再利用できるようにすること。
定期的にバキューム処理を行うことで不要領域が大量に残ることによる性能低下を防ぐ。

pg_vacuum.png

  1. BBBをBBB'に更新。ページ2が不要領域となり、ページ4が新たに追加される
  2. ページを上から順に確認
  3. 2で取得したページが必要領域か不要領域かを確認
  4. 3で不要領域となっているページを再利用対象ページとして空き領域マップに登録

パラメータチューニングの勘所

CPU

クライアントからの接続数だけバックエンドプロセスが生成されるので、プロセスの数が多い分、CPUによるプロセスの切り替え(コンテキストスイッチ)が発生する。
max_connections などのパラメータに適切な値を設定しCPUの負荷をおさえる。

パラメータ 説明
max_connections 最大同時接続数
superuser_reserved_connections スーパーユーザの最大同時接続数。

一般ユーザの最大同時接続数は、max_connections - superuser_reserved_connecitons - スタンバイの数 となる

メモリ

直接ディスクへアクセスせずにメモリ上に展開されているデータにアクセスすることで、パフォーマンスの向上をはかっている。
そのためどのくらいのメモリ領域を確保するかがポイントになる。

共有メモリ

OS側の設定

共有メモリの領域は、サーバの起動時にOSのシステムコールにより確保される。
実際には下記のカーネルパラメータにてサーバ全体で使用できる共有メモリのサイズが決まる。

パラメータ 説明
shmmax 共有メモリの最大容量
shmall 使用可能な共有メモリの総量

PostgreSQL側の設定

PostgreSQL側の設定としては主に以下の2つ。
ちなみに、PostgreSQLの起動時に設定パラメータのチェックが行われ、shmmax < shared_buffers の場合はエラーメッセージが表示される

パラメータ 説明
shared_buffers 共有バッファのサイズを設定。推奨値はサーバ実メモリの25%。
wal_bufferes WALバッファのサイズを設定

プロセスメモリ

パラメータ 説明
work_mem 問い合わせ時のソートやハッシュデータ格納時に使用するメモリのサイズ
maintenance_work_mem Vacuum文やALTER TABLEなどのメンテナンス操作時に使用するメモリのサイズ

ディスク

OS側の設定

I/Oスケジューラの設定として deadline が推奨。
ただしハードウェアの環境によって異なる。

PostgreSQL側の設定

ライタプロセス

ライタプロセスによるテーブルファイルへの書き込みが大量に発生すると、問い合わせ性能がおちる。
以下のパラメータに適切な値を設定し書き込みの周期や上限を設定する

パラメータ 説明
bgwriter_delay ライタプロセスの動作周期
bgwriter_lru_maxpages 一度にライタプロセスが書き込むページ数の上限
bgwriter_lru_multiplier 書き込みが必要になったページのうち、どのくらいの割合を書き込むべきか計算する際に使用

チェックポインタ

以下のパラメータのいずれかの閾値に達すると、共有バッファの情報がデータファイルへ書き込まれる。
書き込み処理の間はI/O負荷が高くなり問い合わせ性能に影響を及ぼす。
適切な値を設定し書き込みの周期や上限を設定する。

パラメータ 説明
checkpoint_segments 最後のチェックポイントからWALセグメントがこの数に達するとチェックポイント処理を行う(PostgreSQL9.4まで)
max_wal_size 最後のチェックポイントからWALバッファがこのサイズに達するとチェックポイント処理を行う(PostgreSQL9.5から)
checkpoint_timeout チェックポインタの動作周期

WALファイル

パラメータ 説明
wal_writer_delay WALライタプロセスの動作周期
max_wal_size 生成されるWALファイルの総数

おわりに

ざっくりとではありますが、今回は理論編ということで基本的な内部の仕組みについてまとめました。
次回は実際に手を動かしてPostgreSQLのインストールからクラスタ構成の構築、アプリとの連携など、実践編としてまとめる予定です。

18
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?