

# RDS for PostgreSQL チューニングの基本概念
<a name="PostgreSQL.Tuning.concepts"></a>

RDS for PostgreSQL データベースをチューニングする前に、待機イベントは何か、なぜそれが発生するのかを確認してください。RDS for PostgreSQL のベーシックメモリとディスクアーキテクチャも確認します。役立つアーキテクチャの図表については、[PostgreSQL](https://en.wikibooks.org/wiki/PostgreSQL/Architecture)ウィキブックを参照してください。

**Topics**
+ [RDS for PostgreSQL 待機イベント](PostgreSQL.Tuning.concepts.waits.md)
+ [RDS for PostgreSQL メモリ](PostgreSQL.Tuning.concepts.memory.md)
+ [RDS for PostgreSQL プロセス](PostgreSQL.Tuning.concepts.processes.md)

# RDS for PostgreSQL 待機イベント
<a name="PostgreSQL.Tuning.concepts.waits"></a>

*待機イベント*は、リソースに対して待機しているリソースを示します。例えば、待機イベント `Client:ClientRead` は RDS for PostgreSQL がクライアントからのデータの受信を待っているときに発生します。セッションは通常、次のようなリソースを待ちます。
+ バッファへのシングルスレッドアクセス (例えば、セッションがバッファを変更しようとした場合など)
+ 別のセッションによって現在ロックされている行
+ 読み込まれたデータファイル
+ ログファイルの書き込み

例えば、クエリを満たすために、セッションで完全なテーブルスキャンを実行することがあります。データがまだメモリ上にない場合、セッションはディスク I/O が完了するまで待機します。バッファがメモリに読み込まれるときは、他のセッションが同じバッファにアクセスしているため、セッションは待機しなければならないことがあります。データベースは、事前定義された待機イベントを使用して待機を記録します。これらのイベントはカテゴリに分類されます。

待機イベント自体では、パフォーマンスの問題は表示されません。例えば、要求されたデータがメモリ上にない場合は、ディスクからデータを読み出す必要があります。あるセッションが更新のために行をロックすると、別のセッションはその行を更新できるようにロック解除されるまで待機します。コミットは、ログファイルへの書き込みが完了するまで待機する必要があります。待機は、データベースが正常に機能するために不可欠です。

一方で、待機イベントが発生すると、通常、パフォーマンスの問題を示します。そのような場合、待機イベントデータを使用して、セッションが時間を費やしている場所を特定できます。例えば、通常は数分で実行されるレポートが数時間かかるようになった場合、合計の待機時間に最も寄与している待機イベントを特定できます。上位の待機イベントの原因を特定できる場合は、パフォーマンス向上のための変更を実行できることがあります。例えば、別のセッションによってロックされている行をセッションが待っている場合、ロックセッションを終了させることができます。

# RDS for PostgreSQL メモリ
<a name="PostgreSQL.Tuning.concepts.memory"></a>

RDS for PostgreSQL メモリは、共有とローカルに分かれています。

**Topics**
+ [RDS for PostgreSQL の共有メモリ](#PostgreSQL.Tuning.concepts.shared)
+ [RDS for PostgreSQL のローカルメモリ](#PostgreSQL.Tuning.concepts.local)

## RDS for PostgreSQL の共有メモリ
<a name="PostgreSQL.Tuning.concepts.shared"></a>

RDS for PostgreSQL では、インスタンスの起動時に共有メモリを割り当てます。共有メモリは複数のサブエリアに分割されています。以下のセクションでは、最も重要なものについて説明します。

**Topics**
+ [共有バッファ](#PostgreSQL.Tuning.concepts.buffer-pool)
+ [ログ先行書き込み (WAL) バッファ](#PostgreSQL.Tuning.concepts.WAL)

### 共有バッファ
<a name="PostgreSQL.Tuning.concepts.buffer-pool"></a>

*共有バッファプール*は、アプリケーション接続によって使用されている、または使用されていたすべてのページを保持する RDS for PostgreSQL メモリ領域です。*ページ*は、ディスクブロックのメモリバージョンです。共有バッファプールは、ディスクから読み込まれたデータブロックをキャッシュします。プールは、ディスクからデータを再読み取りする必要性を減らし、データベースの運用効率を向上させます。

すべてのテーブルとインデックスは、固定サイズのページの配列として格納されます。各ブロックには、行に対応する複数のタプルが含まれています。タプルはどのページにも格納できます。

共有バッファプールには有限メモリがあります。新しいリクエストがメモリにないページを必要とし、メモリがもう存在しない場合、RDS for PostgreSQL は使用頻度の低いページを削除してリクエストに対応します。削除ポリシーは、クロックスイープアルゴリズムによって実装されます。

`shared_buffers`パラメータは、サーバーがデータをキャッシュするメモリ量を決定します。デフォルト値は、DB インスタンスで利用可能なメモリに基づいて `{DBInstanceClassMemory/32768}` バイトに設定されます。

### ログ先行書き込み (WAL) バッファ
<a name="PostgreSQL.Tuning.concepts.WAL"></a>

*ログ先行書き込み (WAL) バッファ*は、RDS for PostgreSQL が後で永続的ストレージに書き込むトランザクションデータを保持します。WAL メカニズムを使用すると、RDS for PostgreSQL は次のことを実行できます。
+ 障害発生後のデータリカバリ
+ ディスクへの頻繁な書き込みを回避し、ディスク I/O を削減

クライアントがデータを変更すると、RDS for PostgreSQL は WAL バッファに変更内容を書き込みます。クライアントが`COMMIT`を発すると、WAL ライタプロセスはトランザクションデータを WAL ファイルに書き込みます。

`wal_level` パラメータは、WAL に書き込む情報量を決定します。`minimal`、`replica`、`logical` などの値を設定できます。

## RDS for PostgreSQL のローカルメモリ
<a name="PostgreSQL.Tuning.concepts.local"></a>

すべてのバックエンドプロセスは、クエリ処理にローカルメモリを割り当てます。

**Topics**
+ [ワークメモリ領域](#PostgreSQL.Tuning.concepts.local.work_mem)
+ [メンテナンス作業用メモリ領域](#PostgreSQL.Tuning.concepts.local.maintenance_work_mem)
+ [テンポラリバッファ領域](#PostgreSQL.Tuning.concepts.temp)

### ワークメモリ領域
<a name="PostgreSQL.Tuning.concepts.local.work_mem"></a>

*ワークメモリ領域*ソートとハッシュを実行するクエリのテンポラリデータを保持します。例えば、`ORDER BY`文節を持つクエリはソートを実行します。クエリは、ハッシュ結合と集約でハッシュテーブルを使用します。

`work_mem` パラメータは、一時ディスクファイルに書き込む前に、内部のソートオペレーションとハッシュテーブルで使用するメモリ量 (メガバイト単位) を指定します。デフォルト値は 4 MB です。複数のセッションを同時に実行でき、各セッションでメンテナンスオペレーションを並行して行うことができます。このため、使用されるワークメモリの合計は、`work_mem`設定の何倍にもなることがあります。

### メンテナンス作業用メモリ領域
<a name="PostgreSQL.Tuning.concepts.local.maintenance_work_mem"></a>

*メンテナンス作業用メモリ領域*は、メンテナンスオペレーション用のデータをキャッシュします。これらの操作には、バキューム処理、インデックス作成、外部キーの追加が含まれます。

`maintenance_work_mem` パラメータは、メンテナンスオペレーションで使用するメモリの最大量 (メガバイト単位) を指定します。デフォルト値は 64 MB です。データベースセッションでは、一度に 1 つのメンテナンスオペレーションしか実行できません。

### テンポラリバッファ領域
<a name="PostgreSQL.Tuning.concepts.temp"></a>

*テンポラリバッファ領域*は、データベースセッションごとにテンポラリテーブルをキャッシュします。

各セッションは、指定した制限まで、必要に応じてテンポラリバッファを割り当てます。セッションが終了すると、サーバーはバッファをクリアします。

`temp_buffers` パラメータは、各セッションで使用する一時バッファの最大数 (メガバイト単位) を設定します。デフォルト値は 8 MB です。セッション内でテンポラリテーブルを初期に使用する前に、`temp_buffers`値を変更できます。

# RDS for PostgreSQL プロセス
<a name="PostgreSQL.Tuning.concepts.processes"></a>

RDS for PostgreSQL では複数のプロセスを使用します。

**Topics**
+ [Postmaster プロセス](#PostgreSQL.Tuning.concepts.postmaster)
+ [バックエンドプロセス](#PostgreSQL.Tuning.concepts.backend)
+ [バックグラウンドプロセス](#PostgreSQL.Tuning.concepts.vacuum)

## Postmaster プロセス
<a name="PostgreSQL.Tuning.concepts.postmaster"></a>

*Postmaster プロセス*は、RDS for PostgreSQL を起動したときに初期のプロセスがスタートされます。Postmaster プロセスには、主に次のようなロールがあります。
+ バックグラウンドプロセスのフォークとモニタリング
+ クライアントプロセスから認証要求を受信し、データベースが要求を処理する前に認証する

## バックエンドプロセス
<a name="PostgreSQL.Tuning.concepts.backend"></a>

Postmaster がクライアント要求を認証する場合、Postmaster は新しいバックエンドプロセスをフォークします。これは postgres プロセスとも呼ばれます。1 つのクライアントプロセスが 1 つのバックエンドプロセスに接続されます。クライアントプロセスとバックエンドプロセスは、Postmaster プロセスの介入なしに直接通信します。

## バックグラウンドプロセス
<a name="PostgreSQL.Tuning.concepts.vacuum"></a>

Postmaster プロセスは、異なるバックエンドタスクを実行するいくつかのプロセスをフォークします。より重要なものとしては、以下のとおりです。
+ WALライター

  RDS for PostgreSQL は WAL (ログ先行書き込み) バッファのデータをログファイルに書き込みます。ログ先行書き込みの原理は、データベースがそれらの変更を説明するログレコードをディスクに書き込むまで、データベースがデータファイルに変更を書き込むことができないということです。WAL メカニズムはディスク I/O を削減し、RDS for PostgreSQL が障害後にデータベースを回復するためにログを使用できるようにします。
+ バックグラウンドライター

  このプロセスは、メモリバッファからデータファイルにダーティ (変更された) ページを定期的に書き込みます。バックエンドプロセスがメモリ上でページを変更すると、ページがダーティになります。
+ オートバキュームデーモン

  最新のデーモンには以下の構成要素があります。
  + オートバキュームランチャー
  + オートバキュームワーカープロセス

  オートバキュームをオンにすると、多数の挿入、更新、または削除されたタプルがあるテーブルを確認します。デーモンには、次のようなロールがあります。
  + 更新または削除された行によって占有されているディスク領域をリカバリまたは再利用する
  + プランナーで使用する統計情報を更新する
  + トランザクション ID のラップアラウンドによる古いデータの損失からの保護

  オートバキューム機能は、`VACUUM`と`ANALYZE`コマンドの実行を自動化するもので、`VACUUM`にはスタンダードとフルのバリエーションがあります。スタンダードバキュームは、他のデータベースオペレーションと並行して実行されます。 `VACUUM FULL`は、作業中のテーブルを排他的にロックする必要があります。そのため、同じテーブルにアクセスするオペレーションと並行して実行することはできません。`VACUUM`は相当量の I/O トラフィックを作成し、他のアクティブなセッションのパフォーマンスが低下する原因となることがあります。