

# RDS for PostgreSQL の待機イベントでのチューニング
<a name="PostgreSQL.Tuning"></a>

待機イベントは RDS for PostgreSQL の重要なチューニングツールです。セッションがリソースを待っている理由とその内容がわかれば、ボトルネックを減少できます。このセクションの情報を使用して、考えられる原因と修正措置を見つけることができます。このセクションでは、PostgreSQL の基本的なチューニングの概念についても説明します。

このセクションの待機イベントは RDS for PostgreSQL 固有のものです。

**Topics**
+ [

# RDS for PostgreSQL チューニングの基本概念
](PostgreSQL.Tuning.concepts.md)
+ [

# RDS for PostgreSQL 待機イベント
](PostgreSQL.Tuning.concepts.summary.md)
+ [

# Client:ClientRead
](wait-event.clientread.md)
+ [

# クライアント: ClientWrite
](wait-event.clientwrite.md)
+ [

# CPU
](wait-event.cpu.md)
+ [

# IO:BufFileRead および IO:BufFileWrite
](wait-event.iobuffile.md)
+ [

# IO:DataFileRead
](wait-event.iodatafileread.md)
+ [

# IO:WALWrite
](wait-event.iowalwrite.md)
+ [

# IPC:parallel 待機イベント
](rpg-ipc-parallel.md)
+ [

# IPC:ProcArrayGroupUpdate
](apg-rpg-ipcprocarraygroup.md)
+ [

# Lock:advisory
](wait-event.lockadvisory.md)
+ [

# Lock:extend
](wait-event.lockextend.md)
+ [

# Lock:Relation
](wait-event.lockrelation.md)
+ [

# Lock:transactionid
](wait-event.locktransactionid.md)
+ [

# Lock:tuple
](wait-event.locktuple.md)
+ [

# LWLock:BufferMapping (LWLock:buffer\$1mapping)
](wait-event.lwl-buffer-mapping.md)
+ [

# LWLock:BufferIO (IPC:BufferIO)
](wait-event.lwlockbufferio.md)
+ [

# LWLock:buffer\$1content (BufferContent)
](wait-event.lwlockbuffercontent.md)
+ [

# LWLock:lock\$1manager (LWLock:lockmanager)
](wait-event.lw-lock-manager.md)
+ [

# LWLock:pg\$1stat\$1statements
](apg-rpg-lwlockpgstat.md)
+ [

# LWLock:SubtransSLRU (LWLock:SubtransControlLock)
](wait-event.lwlocksubtransslru.md)
+ [

# Timeout:PgSleep
](wait-event.timeoutpgsleep.md)
+ [

# Timeout:VacuumDelay
](wait-event.timeoutvacuumdelay.md)

# 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 トラフィックを作成し、他のアクティブなセッションのパフォーマンスが低下する原因となることがあります。

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

次の表では、パフォーマンスの問題を最もよく示す RDS for PostgreSQL の待機イベントと、最も一般的な原因および修正処置をリストアップしています。


| 待機イベント | 定義 | 
| --- | --- | 
|  [Client:ClientRead](wait-event.clientread.md)  |  このイベントは、RDS for PostgreSQL がクライアントからのデータ受信を待っているときに発生します。  | 
|  [クライアント: ClientWrite](wait-event.clientwrite.md)  |  このイベントは、RDS for PostgreSQL がクライアントへのデータ書き込みを待っているときに発生します。  | 
|  [CPU](wait-event.cpu.md)  | この待機イベントは、スレッドが CPU でアクティブであるか CPU の待機中に発生します。 | 
|  [IO:BufFileRead および IO:BufFileWrite](wait-event.iobuffile.md)  |  これらのイベントは、RDS for PostgreSQL がテンポラリファイルを作成するときに発生します。  | 
|  [IO:DataFileRead](wait-event.iodatafileread.md)  |  このイベントは、バックエンドプロセスが必要なページをストレージから読み込む際に、ページが共有メモリで使用できないために接続が待機したときに発生します。  | 
| [IO:WALWrite](wait-event.iowalwrite.md)  | このイベントは、RDS for PostgreSQL が WAL ファイルへの先行書き込みログ (WAL) バッファの書き込みを待機しているときに発生します。  | 
|  [Lock:advisory](wait-event.lockadvisory.md)  |  このイベントは、PostgreSQL アプリケーションがロックを使用して、複数のセッションにわたるアクティビティを調整するときに発生します。  | 
|  [Lock:extend](wait-event.lockextend.md) |  このイベントは、バックエンドプロセスがリレーション拡張のためにロックするのを待機中に、他のプロセスが同じ目的でそのリレーションをロックしているときに発生します。  | 
|  [Lock:Relation](wait-event.lockrelation.md)  |  このイベントは、他のトランザクションによって現在ロックされているテーブルまたはビューに対するロックを取得するためにクエリが待っているときに発生します。  | 
|  [Lock:transactionid](wait-event.locktransactionid.md)  | このイベントは、トランザクションが行レベルロックを待っているときに発生します。 | 
|  [Lock:tuple](wait-event.locktuple.md)  |  このイベントは、バックエンドプロセスがタプルのロック取得を待機中の場合に発生します。  | 
|  [LWLock:BufferMapping (LWLock:buffer\$1mapping)](wait-event.lwl-buffer-mapping.md)  |  このイベントは、セッションがデータブロックを共有バッファプール内のバッファに関連付けるのを待っているときに発生します。  | 
|  [LWLock:BufferIO (IPC:BufferIO)](wait-event.lwlockbufferio.md)  |  このイベントは、RDS for PostgreSQL が、ページへの同時アクセスを試みたときに、他のプロセスが入出力 (I/O) オペレーションを完了するのを待っているときに発生します。  | 
|  [LWLock:buffer\$1content (BufferContent)](wait-event.lwlockbuffercontent.md)  |  このイベントは、セッションがデータページのメモリ内への読み取りまたは書き込みのために待機中、そのデータページが他のセッションで書き込むためにロックされているときに発生します。  | 
|  [LWLock:lock\$1manager (LWLock:lockmanager)](wait-event.lw-lock-manager.md)  | このイベントは、RDS for PostgreSQL エンジンが、高速パスロックが不可能な場合に共有ロックのメモリ領域を維持し、ロックの割り当て、チェック、および解放を行うときに発生します。 | 
|  [LWLock:SubtransSLRU (LWLock:SubtransControlLock)](wait-event.lwlocksubtransslru.md)  |  このイベントは、プロセスがサブトランザクションのシンプルな最も長い時間使われていない (SLRU) キャッシュへのアクセスを待機しているときに発生します。  | 
|  [Timeout:PgSleep](wait-event.timeoutpgsleep.md)  |  このイベントは、サーバープロセスが`pg_sleep`機能を呼び出し、スリープタイムアウトを待っているときに発生します。  | 
|  [Timeout:VacuumDelay](wait-event.timeoutvacuumdelay.md)  | このイベントは、推定コスト制限に達したため、バキュームプロセスがスリープ状態になっていることを示しています。 | 

# Client:ClientRead
<a name="wait-event.clientread"></a>

`Client:ClientRead` イベントは、RDS for PostgreSQL がクライアントからのデータ受信を待っているときに発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.clientread.context.supported)
+ [

## Context
](#wait-event.clientread.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.clientread.causes)
+ [

## アクション
](#wait-event.clientread.actions)

## サポート対象エンジンバージョン
<a name="wait-event.clientread.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL バージョン 10 以降でサポートされています。

## Context
<a name="wait-event.clientread.context"></a>

RDS for PostgreSQL DB インスタンスは、クライアントからのデータ受信を待っています。RDS for PostgreSQL DB インスタンスは、クライアントにさらにデータを送信する前に、クライアントからデータを受信する必要があります。インスタンスがクライアントからデータを受信する前に待機する時間が `Client:ClientRead` イベントとなります。

## 待機時間が増加する原因の可能性
<a name="wait-event.clientread.causes"></a>

`Client:ClientRead`上位待機中に表示されるイベントの一般的な原因には、次のものがあります。

**ネットワークレイテンシーの増加**  
RDS for PostgreSQL DB インスタンスとクライアントの間のネットワークレイテンシーが増加することがあります。ネットワークレイテンシーが高いほど、DB インスタンスがクライアントからデータを受信するために必要な時間が長くなります。

**クライアントへの負荷の増大**  
クライアント側で CPU プレッシャーまたはネットワーク飽和が発生している可能性があります。クライアント側の負荷が増加すると、クライアントから RDS for PostgreSQL DB インスタンスへのデータの転送が遅延する可能性があります。

**過剰なネットワークラウンドトリップ**  
RDS for PostgreSQL DB インスタンスとクライアントの間のネットワークラウンドトリップが多くなると、クライアントから RDS for PostgreSQL DB インスタンスへのデータの転送が遅延する可能性があります。

**大規模なコピーオペレーション**  
コピーオペレーション中、データはクライアントのファイルシステムから RDS for PostgreSQL DB インスタンスに転送されます。DB インスタンスに大量のデータを送信すると、クライアントから DB インスタンスへのデータの転送が遅延する可能性があります。

**アイドル状態のクライアントの接続**  
クライアントが RDS for PostgreSQL DB インスタンスに `idle in transaction` 状態で接続している場合、DB インスタンスは、クライアントがより多くのデータを送信するのを待ったり、コマンドを発したりすることがあります。この状態での接続は、`Client:ClientRead`イベントの増加につながることがあります。

**接続プーリングに使用される pgBouncer**  
pgBouncer には`pkt_buf`という低レベルネットワーク構成設定があり、デフォルトでは 4,096 に設定されています。ワークロードが 4,096 バイトを超えるクエリパケットを pgBouncer を介して 送信する場合は、`pkt_buf`8,192 に設定することをお勧めします。新しい設定で`Client:ClientRead`イベントの数が減らない場合は、`pkt_buf`を16,384 や 32,768 など、より大きな値に設定にすることをお勧めします。クエリテキストが大きい場合は、大きな設定を使用すると特に効果的です。

## アクション
<a name="wait-event.clientread.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。

**Topics**
+ [

### クライアントをインスタンスと同じアベイラビリティーゾーンと VPC サブネットに配置します。
](#wait-event.clientread.actions.az-vpc-subnet)
+ [

### クライアントのスケーリング
](#wait-event.clientread.actions.scale-client)
+ [

### 現行世代のインスタンスを使用
](#wait-event.clientread.actions.db-instance-class)
+ [

### ネットワーク帯域幅の増加
](#wait-event.clientread.actions.increase-network-bandwidth)
+ [

### ネットワークパフォーマンスの最大値をモニタリングする
](#wait-event.clientread.actions.monitor-network-performance)
+ [

### 「トランザクションのアイドル」状態のトランザクションをモニタリングする
](#wait-event.clientread.actions.check-idle-in-transaction)

### クライアントをインスタンスと同じアベイラビリティーゾーンと VPC サブネットに配置します。
<a name="wait-event.clientread.actions.az-vpc-subnet"></a>

ネットワークレイテンシーを減らしてネットワークスループットを向上するには、RDS for PostgreSQL DB インスタンスと同じアベイラビリティーゾーンおよび仮想プライベートクラウド (VPC) サブネットにクライアントを配置します。クライアントが、DB インスタンスにできる限り地理的に近い場所に配置されていることを確認してください。

### クライアントのスケーリング
<a name="wait-event.clientread.actions.scale-client"></a>

Amazon CloudWatch またはその他のホストメトリクスを使用して、クライアント側が現在 CPU またはネットワーク帯域幅、またはその両方によって制約を受けているかどうかを判断します。クライアント側が制約を受けている場合は、それに応じてクライアントをスケーリングします。

### 現行世代のインスタンスを使用
<a name="wait-event.clientread.actions.db-instance-class"></a>

場合によっては、ジャンボフレームをサポートする DB インスタンスクラスを使用していない可能性があります。Amazon EC2 でアプリケーションを実行している場合は、クライアント側に現行世代のインスタンスを使用することを検討してください。また、クライアントのOSで最大送信単位 (MTU) を設定します。この技術では、ネットワークラウンドトリップの数を減らし、ネットワークスループットを向上させることができます。詳細については、「*Amazon EC2 ユーザーガイド*」の「[ジャンボフレーム (9001 MTU)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html#jumbo_frame_instances)」を参照してください。

DB インスタンスクラスの詳細については、「[ DB インスタンスクラス](Concepts.DBInstanceClass.md)」を参照してください。Amazon EC2 インスタンスタイプと同等の DB インスタンスクラスを決定するには、`db.`Amazon EC2 インスタンスタイプの前に配置します。例えば、`r5.8xlarge`Amazon EC2 インスタンスは`db.r5.8xlarge`DB インスタンスクラスと同等です。

### ネットワーク帯域幅の増加
<a name="wait-event.clientread.actions.increase-network-bandwidth"></a>

`NetworkReceiveThroughput` および `NetworkTransmitThroughput` の Amazon CloudWatch メトリクスを使用して、DB インスタンス上の着信および発信ネットワークトラフィックをモニタリングします。これらのメトリックは、ネットワーク帯域幅がワークロードに十分であるかどうかを判断するのに役立ちます。

ネットワーク帯域幅が十分でない場合は、増加してください。AWSクライアントまたは DB インスタンスがネットワーク帯域幅の制限に達している場合、帯域幅を増やす唯一の方法は、DB インスタンスのサイズを増加することことです。詳細については、「[DB インスタンスクラスタイプ](Concepts.DBInstanceClass.Types.md)」を参照してください。

CloudWatch のメトリクスの詳細については、「[Amazon RDS の Amazon CloudWatch メトリクス](rds-metrics.md)」を参照してください。

### ネットワークパフォーマンスの最大値をモニタリングする
<a name="wait-event.clientread.actions.monitor-network-performance"></a>

Amazon EC2 クライアントを使用している場合、Amazon EC2 は、集約されたインバウンドとアウトバウンドのネットワーク帯域幅を含む、ネットワークパフォーマンスメトリックの最大値を提供します。また、パケットが期待どおりに返されることを確認する接続追跡、ドメインネームシステム (DNS) などのサービスへのリンクローカルサービスアクセスも提供します。これらの最大値をモニタリングするには、現在の拡張ネットワークドライバーを使用し、クライアントのネットワークパフォーマンスをモニタリングします。

詳細については、「*Amazon EC2 ユーザーガイド*」の「[Amazon EC2 インスタンスのネットワークパフォーマンスのモニタリング](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-network-performance-ena.html)」および「*Amazon EC2 ユーザーガイド*」の「[Amazon EC2 インスタンスのネットワークパフォーマンスのモニタリング](https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/monitoring-network-performance-ena.html)」を参照してください。

### 「トランザクションのアイドル」状態のトランザクションをモニタリングする
<a name="wait-event.clientread.actions.check-idle-in-transaction"></a>

`idle in transaction`接続の数が増えているかどうかをチェックします。これを行うには、`pg_stat_activity`テーブルの`state`列をモニタリングします。次のようなクエリを実行することで、接続出典を特定できる場合があります。

```
select client_addr, state, count(1) from pg_stat_activity 
where state like 'idle in transaction%' 
group by 1,2 
order by 3 desc
```

# クライアント: ClientWrite
<a name="wait-event.clientwrite"></a>

`Client:ClientWrite` イベントは、RDS for PostgreSQL がクライアントへのデータ書き込みを待っているときに発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.clientwrite.context.supported)
+ [

## Context
](#wait-event.clientwrite.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.clientwrite.causes)
+ [

## アクション
](#wait-event.clientwrite.actions)

## サポート対象エンジンバージョン
<a name="wait-event.clientwrite.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL バージョン 10 以降でサポートされています。

## Context
<a name="wait-event.clientwrite.context"></a>

クライアントプロセスは、クラスターがさらにデータを送信する前に、RDS for PostgreSQL DB クラスターから受信したすべてのデータを読み込む必要があります。クライアントにより多くのデータを送信する前にクラスターが待機する時間は、`Client:ClientWrite`イベントになります。

RDS for PostgreSQL DB インスタンスとクライアント間のネットワークスループットが低下すると、このイベントが発生することがあります。クライアントの CPU プレッシャーとネットワークの飽和により、このイベントが発生することがあります。*CPU プレッシャー*とは、CPU が完全に使用されており、CPU 時間を待っているタスクがあることです。*ネットワーク飽和度*とは、データベースとクライアント間のネットワークが、処理できるデータ以上のデータを伝送しているときです。

## 待機時間が増加する原因の可能性
<a name="wait-event.clientwrite.causes"></a>

`Client:ClientWrite`上位待機中に表示されるイベントの一般的な原因には、次のものがあります。

**ネットワークレイテンシーの増加**  
RDS for PostgreSQL DB インスタンスとクライアントの間のネットワークレイテンシーが増加することがあります。ネットワークレイテンシーが高いほど、クライアントからデータを受信するために必要な時間が長くなります。

**クライアント側への負荷の増加**  
クライアント側で CPU プレッシャーまたはネットワーク飽和が発生している可能性があります。クライアントの負荷が増加すると、RDS for PostgreSQL DB インスタンスからのデータの受信が遅延します。

**クライアントに送信される大量のデータ**  
RDS for PostgreSQL DB インスタンスがクライアントに大量のデータを送信している可能性があります。クライアントは、クラスターのデータ送信と同じ速度ではデータを受信できない場合があります。大きなテーブルのコピーなどのアクティビティは、`Client:ClientWrite`イベントの増加につながることがあります。

## アクション
<a name="wait-event.clientwrite.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。

**Topics**
+ [

### クライアントをクラスターと同じアベイラビリティーゾーンと VPC サブネットに配置します。
](#wait-event.clientwrite.actions.az-vpc-subnet)
+ [

### 現行世代のインスタンスを使用
](#wait-event.clientwrite.actions.db-instance-class)
+ [

### クライアントに送信するデータ量を減らします。
](#wait-event.clientwrite.actions.reduce-data)
+ [

### クライアントのスケーリング
](#wait-event.clientwrite.actions.scale-client)

### クライアントをクラスターと同じアベイラビリティーゾーンと VPC サブネットに配置します。
<a name="wait-event.clientwrite.actions.az-vpc-subnet"></a>

ネットワークレイテンシーを減らしてネットワークスループットを向上するには、RDS for PostgreSQL DB インスタンスと同じアベイラビリティーゾーンおよび仮想プライベートクラウド (VPC) サブネットにクライアントを配置します。

### 現行世代のインスタンスを使用
<a name="wait-event.clientwrite.actions.db-instance-class"></a>

場合によっては、ジャンボフレームをサポートする DB インスタンスクラスを使用していない可能性があります。Amazon EC2 でアプリケーションを実行している場合は、クライアント側に現行世代のインスタンスを使用することを検討してください。また、クライアントのOSで最大送信単位 (MTU) を設定します。この技術では、ネットワークラウンドトリップの数を減らし、ネットワークスループットを向上させることができます。詳細については、「*Amazon EC2 ユーザーガイド*」の「[ジャンボフレーム (9001 MTU)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/network_mtu.html#jumbo_frame_instances)」を参照してください。

DB インスタンスクラスの詳細については、「[ DB インスタンスクラス](Concepts.DBInstanceClass.md)」を参照してください。Amazon EC2 インスタンスタイプと同等の DB インスタンスクラスを決定するには、`db.`Amazon EC2 インスタンスタイプの前に配置します。例えば、`r5.8xlarge`Amazon EC2 インスタンスは`db.r5.8xlarge`DB インスタンスクラスと同等です。

### クライアントに送信するデータ量を減らします。
<a name="wait-event.clientwrite.actions.reduce-data"></a>

可能であれば、RDS for PostgreSQL DB インスタンスがクライアントに送信するデータ量を減らすようにアプリケーションを調整します。このような調整を行うと、クライアントの CPU やネットワークの競合を軽減します。

### クライアントのスケーリング
<a name="wait-event.clientwrite.actions.scale-client"></a>

Amazon CloudWatch またはその他のホストメトリクスを使用して、クライアント側が現在 CPU またはネットワーク帯域幅、またはその両方によって制約を受けているかどうかを判断します。クライアント側が制約を受けている場合は、それに応じてクライアントをスケーリングします。

# CPU
<a name="wait-event.cpu"></a>

この待機イベントは、スレッドが CPU でアクティブであるか CPU の待機中に発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.cpu.context.supported)
+ [

## Context
](#wait-event.cpu.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.cpu.causes)
+ [

## アクション
](#wait-event.cpu.actions)

## サポート対象エンジンバージョン
<a name="wait-event.cpu.context.supported"></a>

この待機イベント情報は、すべての RDS for PostgreSQL のすべてのバージョンに関連しています。

## Context
<a name="wait-event.cpu.context"></a>

*中央処理装置 (CPU)*は、命令を実行するコンピュータのコンポーネントです。例えば、CPU 命令は演算処理を実行し、メモリ上でデータを交換します。クエリがデータベースエンジンを介して実行する命令の数が増えると、クエリの実行にかかる時間が長くなります。*CPU スケジューリング*は、CPU にプロセス時間を与えています。スケジューリングは、OS のカーネルによってオーケストレーションされます。

**Topics**
+ [

### この待機の発生時期を確認する方法
](#wait-event.cpu.when-it-occurs)
+ [

### DbLoadCPU メトリクス
](#wait-event.cpu.context.dbloadcpu)
+ [

### os.cpuUtilization メトリック
](#wait-event.cpu.context.osmetrics)
+ [

### CPU スケジューリングの原因の可能性
](#wait-event.cpu.context.scheduling)

### この待機の発生時期を確認する方法
<a name="wait-event.cpu.when-it-occurs"></a>

この`CPU`待機イベントは、バックエンドプロセスが CPU でアクティブであるか、CPU を待っていることを示します。クエリに次の情報が表示されると、発生していることがわかります。
+  「`pg_stat_activity.state`」 列には値`active`があります。
+ `pg_stat_activity`の`wait_event_type`および`wait_event`の列は、両方とも`null`です。

CPU を使用中または待機中のバックエンドプロセスを確認するには、次のクエリを実行します。

```
SELECT * 
FROM   pg_stat_activity
WHERE  state = 'active'
AND    wait_event_type IS NULL
AND    wait_event IS NULL;
```

### DbLoadCPU メトリクス
<a name="wait-event.cpu.context.dbloadcpu"></a>

CPU の Performance Insights のメトリクスは `DBLoadCPU` です。`DBLoadCPU`の値は、Amazon CloudWatch メトリクスの値とは異なる場合があります`CPUUtilization`。後者のメトリクスは、データベースインスタンスのハイパーバイザーから収集されます。

### os.cpuUtilization メトリック
<a name="wait-event.cpu.context.osmetrics"></a>

Performance Insights OS のメトリクスは、CPU 使用率に関する詳細情報を提供します。例えば、次のメトリクスを表示できます。
+ `os.cpuUtilization.nice.avg`
+ `os.cpuUtilization.total.avg`
+ `os.cpuUtilization.wait.avg`
+ `os.cpuUtilization.idle.avg`

Performance Insights は、データベースエンジンによる CPU 使用率を`os.cpuUtilization.nice.avg`のように報告します。

### CPU スケジューリングの原因の可能性
<a name="wait-event.cpu.context.scheduling"></a>

 オペレーティングシステム (OS) カーネルは、CPU のスケジューリングを処理します。CPU が*アクティブ*な場合、プロセスがスケジューリングされるのを待機する必要がある場合があります。計算の実行中は、CPU はアクティブです。また、実行されていないアイドルスレッド、つまりメモリ I/O の待機中もアクティブになります。このタイプの I/O は、一般的なデータベースワークロードの大部分を占めています。

以下の条件が満たされると、プロセスは CPU でスケジュールされるのを待機する可能性があります。
+ CloudWatch`CPUUtilization`メトリクスは 100% に近いです。
+ 平均ロードは vCPUs の数よりも大きく、ロードが重いことを示しています。このメトリクスは、`loadAverageMinute`Performance Insights の OS メトリクスセクションで見ることができます。

## 待機時間が増加する原因の可能性
<a name="wait-event.cpu.causes"></a>

CPU 待機イベントが通常よりも頻繁に発生する場合は、パフォーマンスの問題を示している可能性があり、典型的な原因は次のとおりです。

**Topics**
+ [

### 突然のスパイクの原因の可能性
](#wait-event.cpu.causes.spikes)
+ [

### 長期の高周波の原因の可能性
](#wait-event.cpu.causes.long-term)
+ [

### コーナーケース
](#wait-event.cpu.causes.corner-cases)

### 突然のスパイクの原因の可能性
<a name="wait-event.cpu.causes.spikes"></a>

突然のスパイクの原因として最も可能性の高いものは次のとおりです。
+ アプリケーションがデータベースへの同時接続を開きすぎています。このシナリオは「接続ストーム」と呼ばれます。
+ アプリケーションのワークロードは、次のいずれかの方法で変更されました。
  + 新しいクエリ
  + データセットのサイズの増加
  + インデックスのメンテナンスまたは作成
  + 新しい関数
  + 新しいオペレーター
  + パラレルクエリ実行の増加
+ クエリ実行プランが変更されました。場合によっては、変更によってバッファが増加することがあります。例えば、以前はインデックスを使用していたクエリが、現在はシーケンシャルスキャンを使用します。この場合、同じ目標を達成するには、クエリがより多くの CPU を必要とします。

### 長期の高周波の原因の可能性
<a name="wait-event.cpu.causes.long-term"></a>

長期間にわたって再発するイベントの原因として最も可能性の高いもの:
+ CPU で同時に実行されているバックエンドプロセスが多すぎます。これらのプロセスは、パラレルワーカーにすることができます。
+ クエリのパフォーマンスは、大量のバッファを必要とするため最適ではありません。

### コーナーケース
<a name="wait-event.cpu.causes.corner-cases"></a>

考えられる原因のいずれも実際の原因ではない場合は、以下のような状況が発生することがあります。
+ CPU がプロセスを入れ替えています。
+ *huge pages* 機能が無効になっていると、CPU がページテーブルエントリを管理している可能性があります。このメモリ管理機能は、micro、small、medium 以外のすべての DB インスタンスクラスで、デフォルトでオンになっています。詳細については、「[RDS for PostgreSQL の ヒュージページ](PostgreSQL.Concepts.General.FeatureSupport.HugePages.md)」を参照してください。

## アクション
<a name="wait-event.cpu.actions"></a>

`CPU` 待機イベントがデータベースアクティビティを占領している場合でも、必ずしもパフォーマンスの問題を示すわけではありません。パフォーマンスが低下した場合にのみ、このイベントに応答します。

**Topics**
+ [

### データベースが CPU の増加原因かどうかを調べる
](#wait-event.cpu.actions.db-CPU)
+ [

### 接続数が増加したかどうかを判断する
](#wait-event.cpu.actions.connections)
+ [

### ワークロードの変更に対応
](#wait-event.cpu.actions.workload)

### データベースが CPU の増加原因かどうかを調べる
<a name="wait-event.cpu.actions.db-CPU"></a>

`os.cpuUtilization.nice.avg`Performance Insights のメトリクスを検証します。この値が CPU 使用率よりはるかに小さい場合、データベース以外のプロセスが CPU の主な原因となっています。

### 接続数が増加したかどうかを判断する
<a name="wait-event.cpu.actions.connections"></a>

`DatabaseConnections`Amazon CloudWatch のメトリクスを検証します。アクションは、CPU の待機イベントが増加した期間中の数値の増減によって異なります。

#### 接続数が増加した
<a name="wait-event.cpu.actions.connections.increased"></a>

接続数が増えた場合は、CPU を消費しているバックエンドプロセスの数と vCPUs の数を比較します。以下のシナリオが考えられます。
+ CPU を消費するバックエンドプロセスの数が、vCPUs の数より少なくなっています。

  この場合、接続数は問題ではありません。ただし、それでも CPU 使用率を下げようとすることがあります。
+ CPU を消費するバックエンドプロセスの数が vCPUs の数を超えています。

  このような場合は、以下のオプションを検討します。
  + データベースに接続されているバックエンドプロセスの数を減らします。例えば、RDS Proxy などの接続プーリングソリューションを実装します。詳細については[Amazon RDS Proxy ](rds-proxy.md)を参照してください。
  + インスタンスサイズをアップグレードして vCPUs の数を増やします。
  + 一部の読み取り専用ワークロードをリーダーノードにリダイレクトします (該当する場合)。

#### 接続は増加しなかった
<a name="wait-event.cpu.actions.connections.decreased"></a>

`blks_hit`Performance Insights のメトリクスを検証します。`blks_hit`と CPU 使用率の増加の相関関係を探してください。以下のシナリオが考えられます。
+ CPU 使用率と`blks_hit`が相関しています。

  この場合、CPU 使用率にリンクされている上位 SQL ステートメントを検索し、プランの変更を検討します。以下のいずれかの対策を使用できます。
  + 計画をマニュアルで説明し、予想される実行プランと比較します。
  + 秒単位のブロックヒット数とローカルブロックヒット数の増加を確認します。Performance Insights ダッシュボードの**上位 SQL**セクションで、**Preferences (設定) **を選択します。
+ CPU 使用率と`blks_hit`には相関関係がありません。

  このような場合は、次のいずれかに該当するかどうかを判断します。
  + アプリケーションは、データベースとの接続と切断を高速で行っています。

    `log_connections`および`log_disconnections`をオンにして、PostgreSQL のログを分析します。`pgbadger`ログアナライザの使用を検討します。詳細については、「[https://github.com/darold/pgbadger](https://github.com/darold/pgbadger)」を参照してください。
  + OS はオーバーロード状態です。

    この場合、Performance Insights は、バックエンドプロセスが通常よりも長い時間 CPU を消費していることを示しています。Performance Insights の`os.cpuUtilization`メトリクスサイトまたは`CPUUtilization`CloudWatch のメトリクスでエビデンスを探します。OS がオーバーロード状態になっている場合は、拡張モニタリングのメトリックを参照してさらに診断します。具体的には、プロセスリストと各プロセスが消費する CPU の割合を確認します。
  + 上位 SQL ステートメントが消費する CPU が多すぎます。

    CPU 使用率とリンクするステートメントを検証し、CPU の使用率を減らせるかどうかを確認します。`EXPLAIN`コマンドを実行し、最も影響が大きいプランノードにフォーカスします。PostgreSQL の実行計画ビジュアライザーの使用を検討してください。このツールを試すには、[http://explain.dalibo.com/](http://explain.dalibo.com/)を参照してください。

### ワークロードの変更に対応
<a name="wait-event.cpu.actions.workload"></a>

ワークロードが変更された場合は、次のタイプの変更を探します。

新しいクエリ  
新しいクエリが想定されているかどうかを確認します。その場合は、その実行計画と秒単位の実行数が想定されていることを確認してください。

データセットのサイズの増加  
パーティショニングが未実装の場合は、それが役立つかどうかを判断します。この戦略では、クエリで取得する必要があるページ数を減らすことができます。

インデックスのメンテナンスまたは作成  
メンテナンスのスケジュールが想定されているかどうかを確認します。ベストプラクティスは、ピークアクティビティ以外のメンテナンスアクティビティをスケジュールすることです。

新しい関数  
これらの機能がテスト中に想定したとおりに動作するかどうかを確認します。具体的には、秒単位の実行数が想定されているかどうかを確認します。

新しいオペレーター  
テスト中に想定どおりに動作するかどうかを確認します。

パラレルクエリの実行の増加  
以下のいずれかの状況が発生するかどうかを確認します。  
+ 関連する関係やインデックスのサイズが突然大きくなり、`min_parallel_table_scan_size`または`min_parallel_index_scan_size`は大きく異なるようになりました。
+ 「`parallel_setup_cost`または`parallel_tuple_cost`」に最近変更が加えられました。
+ 「`max_parallel_workers`または`max_parallel_workers_per_gather`」に最近変更が加えられました。

# IO:BufFileRead および IO:BufFileWrite
<a name="wait-event.iobuffile"></a>

`IO:BufFileRead` と `IO:BufFileWrite` イベントは、RDS for PostgreSQL がテンポラリファイルを作成するときに発生します。作業メモリパラメータが現在の定義より多くのメモリを必要とするオペレーションは、テンポラリデータを永続的ストレージに書き込みます。この操作は「*spilling to disk (ディスクへの流出)*」と呼ばれることがあります。一時ファイルとその使用方法の詳細については、「[PostgreSQL による一時ファイルの管理](PostgreSQL.ManagingTempFiles.md)」を参照してください。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.iobuffile.context.supported)
+ [

## Context
](#wait-event.iobuffile.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.iobuffile.causes)
+ [

## アクション
](#wait-event.iobuffile.actions)

## サポート対象エンジンバージョン
<a name="wait-event.iobuffile.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="wait-event.iobuffile.context"></a>

`IO:BufFileRead`そして`IO:BufFileWrite`は、作業メモリ領域とメンテナンス作業用メモリ領域に関連します。これらのローカルメモリ領域の詳細については、PostgreSQL ドキュメントの「[リソース消費](https://www.postgresql.org/docs/current/runtime-config-resource.html)」を参照してください。

デフォルト値は `work_mem` 4 MB です。一つのセッションがパラレルにオペレーションを実行する場合、パラレル処理を行う各ワーカーは 4 MB のメモリを使用します。このため、`work_mem`を慎重に設定してください。値を大きくしすぎると、多くのセッションを実行しているデータベースがメモリを過剰に消費することがあります。値を低く設定しすぎると、RDS for PostgreSQL はローカルストレージに一時ファイルを作成します。これらのテンポラリファイルのためのディスク I/O により、パフォーマンスが低下する可能性があります。

次のようなイベントが発生する場合、データベースがテンポラリファイルを生成している可能性があります。

1. 可用性の急激な低下

1. 空き領域の高速リカバリ

また、「チェーンソー」のパターンが表示されるかもしれません。このパターンは、データベースが小さなファイルを常に作成していることを示す可能性があります。

## 待機時間が増加する原因の可能性
<a name="wait-event.iobuffile.causes"></a>

一般に、これらの待機イベントは、`work_mem`または`maintenance_work_mem`パラメータが割り当てられるよりも多くのメモリを消費するオペレーションによって発生します。補うために、オペレーションはテンポラリファイルに書き込みます。`IO:BufFileRead`そして`IO:BufFileWrite`イベントの一般的な原因には、次のようなものがあります。

**作業用メモリ領域に存在するメモリより多くのメモリを必要とするクエリ**  
次の特性を持つクエリは、作業メモリ領域を使用します。  
+ ハッシュ結合
+ `ORDER BY` 句
+ `GROUP BY` 句
+ `DISTINCT`
+ ウィンドウ関数
+ `CREATE TABLE AS SELECT`
+ REFRESH MATERIALIZED VIEW

**メンテナンス作業メモリ領域に存在するメモリより多くのメモリを必要とするステートメント**  
次のステートメントは、メンテナンス作業メモリ領域を使用します。  
+ `CREATE INDEX`
+ `CLUSTER`

## アクション
<a name="wait-event.iobuffile.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。

**Topics**
+ [

### 問題の特定
](#wait-event.iobuffile.actions.problem)
+ [

### ジョイントクエリを検証する
](#wait-event.iobuffile.actions.joins)
+ [

### ORDER BY クエリと GROUP BY クエリを検証する
](#wait-event.iobuffile.actions.order-by)
+ [

### DISTINCT オペレーションの使用を避ける
](#wait-event.iobuffile.actions.distinct)
+ [

### GROUP BY 関数の代わりにウィンドウ関数の使用を検討してください。
](#wait-event.iobuffile.actions.window)
+ [

### マテリアライズドビューと CTAS ステートメントの調査
](#wait-event.iobuffile.actions.mv-refresh)
+ [

### インデックスの再構築時に pg\$1repack を使用する
](#wait-event.iobuffile.actions.pg_repack)
+ [

### テーブルをクラスター化するときに maintenance\$1work\$1mem を増やす
](#wait-event.iobuffile.actions.cluster)
+ [

### IO:BufFileRead および IO:BufFileWrite を防ぐためにメモリを調整します
](#wait-event.iobuffile.actions.tuning-memory)

### 問題の特定
<a name="wait-event.iobuffile.actions.problem"></a>

一時ファイルの使用状況は、Performance Insights で直接表示できます。詳細については、「[Performance Insights を使用した一時ファイルの使用状況の確認](PostgreSQL.ManagingTempFiles.Example.md)」を参照してください。Performance Insights を無効にすると、`IO:BufFileRead` および `IO:BufFileWrite` オペレーションが増加することがあります。

問題の原因を特定するには、指定したしきい値 KB を超える一時ファイルを生成するすべてのクエリをログに記録するように `log_temp_files` パラメータを設定できます。デフォルトでは、`log_temp_files` は `-1` に設定され、このロギング機能は無効になります。このパラメータを `0` に設定した場合は、RDS for PostgreSQL はすべての一時ファイルをログに記録します。値を `1024` に設定した場合、RDS for PostgreSQL は 1 MB を超える一時ファイルを生成するすべてのクエリをログに記録します。`log_temp_files`についての詳細は、PostgreSQL ドキュメントの[Error reporting and logging](https://www.postgresql.org/docs/current/runtime-config-logging.html) を参照してください。

### ジョイントクエリを検証する
<a name="wait-event.iobuffile.actions.joins"></a>

クエリでは、結合が使用されている可能性があります。例えば、次のクエリは 4 つのテーブルをジョイントします。

```
SELECT * 
       FROM "order" 
 INNER JOIN order_item 
       ON (order.id = order_item.order_id)
 INNER JOIN customer 
       ON (customer.id = order.customer_id)
 INNER JOIN customer_address 
       ON (customer_address.customer_id = customer.id AND 
           order.customer_address_id = customer_address.id)
 WHERE customer.id = 1234567890;
```

テンポラリファイル使用量が急増する原因は、クエリ自体の問題の可能性があります。例えば、壊れた節はジョイントを適切にフィルタリングしない可能性があります。次の例では 2 番目の内部ジョイントを考えてみましょう。

```
SELECT * 
       FROM "order"
 INNER JOIN order_item 
       ON (order.id = order_item.order_id)
 INNER JOIN customer 
       ON (customer.id = customer.id)
 INNER JOIN customer_address 
       ON (customer_address.customer_id = customer.id AND 
           order.customer_address_id = customer_address.id)
 WHERE customer.id = 1234567890;
```

前のクエリが誤って`customer.id`を`customer.id`にジョイントし、すべての顧客とすべての注文の間にデカルト積を生成します。このタイプの偶発的なジョイントは、大きなテンポラリファイルを生成します。テーブルのサイズによっては、デカルトクエリでストレージがいっぱいになることもあります。以下の条件を満たす場合は、アプリケーションにデカルトジョインが生成される場合があります。
+ ストレージの可用性が大きく急激に低下し、その後、高速リカバリが起こります。
+ インデックスは作成されていません。
+ `CREATE TABLE FROM SELECT`ステートメントは発行されていません。
+ マテリアライズドビューはリフレッシュされません。

テーブルが適切なキーを使用してジョイントされているかどうかを確認するには、クエリおよびオブジェクト関係マッピングディレクティブを調べます。アプリケーションの特定のクエリは常に呼び出されるわけではなく、一部のクエリは動的に生成されることに注意してください。

### ORDER BY クエリと GROUP BY クエリを検証する
<a name="wait-event.iobuffile.actions.order-by"></a>

場合によっては、`ORDER BY`節を使用するとテンポラリファイルが過剰になる可能性があります。以下のガイドラインを検討します。
+ 順序付けが必要な場合のみ、`ORDER BY`に列を含めてください。このガイドラインは、数千行を返し、`ORDER BY`節で多数の列を指定するクエリでは特に重要です。
+ `ORDER BY`節が同じ昇順または降順の列にマッチする場合、高速化するためにインデックスの作成を検討します。パーシャルインデックスのほうが小さいため好ましいです。小さいインデックスは、より迅速に読み込まれ、トラバースされます。
+ NULL 値を受け入れることができる列のインデックスを作成する場合は、NULL 値をインデックスの最後に格納するか、先頭に格納するかを検討します。

  可能であれば、結果セットをフィルタリングして、順序付けが必要な行の数を減らします。`WITH`節ステートメントまたはサブクエリを使用する場合、内部クエリが結果セットを生成し、外部クエリに渡すことに注意してください。クエリが行をより多くフィルタリングすると、クエリが行う必要がある順序付けは減ります。
+ 完全な結果セットを取得する必要がない場合は、`LIMIT`節を使用します。例えば、上位 5 行だけが必要な場合、`LIMIT`節を使用したクエリは結果を生成し続けることはありません。このように、クエリに必要なメモリとテンポラリファイルが減ります。

`GROUP BY` 句を使用するクエリは、テンポラリファイルを要求することもできます。`GROUP BY` クエリは、次のような関数を使用して値を要約します。
+ `COUNT`
+ `AVG`
+ `MIN`
+ `MAX`
+ `SUM`
+ `STDDEV`

`GROUP BY`クエリをチューニングするには、`ORDER BY`クエリの推奨事項に従ってください。

### DISTINCT オペレーションの使用を避ける
<a name="wait-event.iobuffile.actions.distinct"></a>

可能であれば、`DISTINCT`オペレーションを使用して重複した行を削除することは避けてください。クエリが返す行が不要かつ重複していればいるほど、V`DISTINCT`オペレーションのコストは高くなります。可能であれば、異なるテーブルに対して同じフィルターを使用している場合でも、`WHERE`節でフィルターを追加してください。クエリをフィルタリングして正しく結合すると、パフォーマンスが向上し、リソースの使用量が削減されます。また、誤ったレポートや結果を防ぐことができます。

`DISTINCT`を同じテーブルの複数の行に使用する必要がある場合、複合インデックスの作成を検討してください。インデックスに複数の列をグループ化すると、個別の行を評価する時間を短縮できます。また、RDS for PostgreSQL バージョン 10 以降を使用している場合は、`CREATE STATISTICS` コマンドを使用して複数の列間で統計を関連付けられます。

### GROUP BY 関数の代わりにウィンドウ関数の使用を検討してください。
<a name="wait-event.iobuffile.actions.window"></a>

`GROUP BY`を使用すると、結果セットを変更し、集計結果を取得できます。ウィンドウ関数を使用すると、結果セットを変更せずにデータを集計できます。ウィンドウ関数は、`OVER`句を使用して、クエリによって定義されたセット間で計算を実行し、ある行を別の行に関連付けます。ウィンドウ関数に含まれるすべての`GROUP BY`関数は使用できますが、次のような関数も使用可能です。
+ `RANK`
+ `ARRAY_AGG`
+ `ROW_NUMBER`
+ `LAG`
+ `LEAD`

ウィンドウ関数によって生成されるテンポラリファイルの数を最小限に抑えるには、2 つの異なる集計が必要な場合は同じ結果セットの重複を削除してください。次のクエリについて考えます。

```
SELECT sum(salary) OVER (PARTITION BY dept ORDER BY salary DESC) as sum_salary
     , avg(salary) OVER (PARTITION BY dept ORDER BY salary ASC) as avg_salary
  FROM empsalary;
```

`WINDOW`節のクエリは、次のように書き換えることができます。

```
SELECT sum(salary) OVER w as sum_salary
         , avg(salary) OVER w as_avg_salary
    FROM empsalary
  WINDOW w AS (PARTITION BY dept ORDER BY salary DESC);
```

デフォルトでは、RDS for PostgreSQL 実行プランナーは類似したノードを統合し、オペレーションが重複しないようにします。ただし、ウィンドウブロックに明示的な宣言を使用すると、クエリをより簡単に維持できます。また、重複を防止するとパフォーマンスの向上につながることがあります。

### マテリアライズドビューと CTAS ステートメントの調査
<a name="wait-event.iobuffile.actions.mv-refresh"></a>

マテリアライズドビューがリフレッシュされると、クエリが実行されます。このクエリには、`GROUP BY`、`ORDER BY`、`DISTINCT`のような操作を含めることができます。リフレッシュ中に、大量のテンポラリファイルや待機イベント`IO:BufFileWrite`および`IO:BufFileRead`が発生することがあります。同様に、`SELECT`に基づいてテーブルを作成すると、`CREATE TABLE`ステートメントはクエリを実行します。必要なテンポラリファイルを減らすには、クエリを最適化します。

### インデックスの再構築時に pg\$1repack を使用する
<a name="wait-event.iobuffile.actions.pg_repack"></a>

インデックスを作成すると、エンジンは結果セットを順序付けます。テーブルのサイズが大きくなり、インデックスで指定された列の値が多様化していくと、テンポラリファイルはより多くの領域を必要とします。ほとんどの場合、メンテナンス作業のメモリ領域を変更しなければ、大きなテーブルのテンポラリファイルの作成を防ぐことはできません。`maintenance_work_mem` の詳細については、PostgreSQL のドキュメントの「[https://www.postgresql.org/docs/current/runtime-config-resource.html](https://www.postgresql.org/docs/current/runtime-config-resource.html)」を参照してください。

大きなインデックスを再作成するときに考えられる回避策としては、pg\$1repack 拡張機能を使用することが挙げられます。詳細については、「pg\$1repack のドキュメント」で「[最小限のロックで PostgreSQL データベース内のテーブルを再編成する](https://reorg.github.io/pg_repack/)」を参照してください。RDS for PostgreSQL DB インスタンスに対する拡張機能の設定については、「[pg\$1repack 拡張機能を使用して、テーブルやインデックスの膨張を抑制する](Appendix.PostgreSQL.CommonDBATasks.pg_repack.md)」を参照してください。

### テーブルをクラスター化するときに maintenance\$1work\$1mem を増やす
<a name="wait-event.iobuffile.actions.cluster"></a>

`CLUSTER`コマンドは、*index\$1name*で指定した既存のインデックスに基づいて、*table\$1name*で指定したテーブルをクラスター化します。RDS for PostgreSQL は、指定されたインデックスの順序に一致するようにテーブルを物理的に再作成します。

磁気ストレージが普及していたころは、ストレージのスループットが限られていたため、クラスター化が一般的でした。今では、SSD ベースのストレージが一般的となり、クラスター化はあまり一般的ではなくなっています。ただし、テーブルをクラスター化すると、テーブルのサイズ、インデックス、クエリなどによってパフォーマンスが多少向上することがあります。

`CLUSTER`コマンドを実行して、待機イベント`IO:BufFileWrite`、`IO:BufFileRead`をモニタリングし、`maintenance_work_mem`をチューニングします。メモリサイズをかなり大きくしてください。高い値は、エンジンがクラスター化オペレーションのためにより多くのメモリを使用できることを意味します。

### IO:BufFileRead および IO:BufFileWrite を防ぐためにメモリを調整します
<a name="wait-event.iobuffile.actions.tuning-memory"></a>

状況によっては、メモリのチューニングが必要です。以下のような適切なパラメータを使用して、消費領域にわたってメモリのバランスを取ることが目的です。
+ `work_mem` 値。
+ `shared_buffers` を割り引いた後の残りのメモリ
+ `max_connections`で制限されるオープンおよび使用中の最大接続数

これらのメモリのチューニングの詳細については、PostgreSQL ドキュメントの「[リソース消費](https://www.postgresql.org/docs/current/runtime-config-resource.html)」を参照してください。

#### 作業メモリ領域のサイズを拡大する
<a name="wait-event.iobuffile.actions.tuning-memory.work-mem"></a>

状況によっては、セッションで使用されるメモリを増やすことが唯一の選択肢となることもあります。クエリが正しく記述され、ジョイントに正しいキーを使用している場合は、`work_mem`値の増加を検討してください。

クエリが生成するテンポラリファイルの数を調べるには、`log_temp_files` を `0` に設定します。`work_mem` 値をログで識別される最大値まで上げると、クエリでテンポラリファイルが生成されるのを防ぎます。ただし、`work_mem`は各接続またはパラレルワーカーにプランノードあたりの最大値を設定します。データベースに 5,000 の接続があり、それぞれが 256 MiB のメモリを使用する場合、エンジンは 1.2 TiB の RAM を必要とします。そのため、インスタンスのメモリが不足する可能性があります。

#### 共有バッファプールに十分なメモリを予約する
<a name="wait-event.iobuffile.actions.tuning-memory.shared-pool"></a>

データベースでは、作業用メモリ領域だけでなく、共有バッファプールなどのメモリ領域が使用されます。`work_mem`を増加する前に、これらの追加メモリ領域の要件を考慮してください。

例えば、RDS for PostgreSQL インスタンスクラスが db.r5.2xlarge であると仮定します。このクラスには 64 GiB のメモリがあります。デフォルトでは、メモリの 25% が共有バッファプール用に予約されています。共有メモリ領域に割り当てられた量を引くと、16,384 MB が残ります。OS やエンジンもメモリを必要とするため、残りのメモリを作業メモリ領域にのみ割り当てないでください。

`work_mem`に割り当て可能なメモリはインスタンスクラスによって異なります。より大きなインスタンスクラスを使用すると、より多くのメモリが使用できます。ただし、前の例では 16 GiB 以上は使用できません。そうでなければ、メモリ不足に陥ったときにインスタンスが使用できなくなります。インスタンスを利用できない状態から回復するには、RDS for PostgreSQL オートメーションサービスが自動的に再起動します。

#### 接続の数を管理する
<a name="wait-event.iobuffile.actions.tuning-memory.connections"></a>

データベースインスタンスでの同時接続が 5,000 とします。各接続では、`work_mem`のうち少なくとも 4 MiB を使用します。接続に必要なメモリ消費量が多いと、パフォーマンスが低下する可能性があります。これに対して、次のオプションがあります。
+ より大きなインスタンスクラスにアップグレードします。
+ 接続プロキシまたはプーラーを使用することで、データベースの同時接続の数を減らします。

プロキシの場合は、アプリケーションに基づいて Amazon RDS プロキシ、pgBouncer、または接続プーラーを検討してください。この解決策は CPU ロードを軽減します。また、すべての接続が作業メモリ領域を必要とする場合のリスクも軽減します。データベース接続数が少ない場合は、`work_mem`の値を増やすことができます。このように、`IO:BufFileRead`そして`IO:BufFileWrite`待機イベントの発生を減らします。また、作業メモリ領域で待っているクエリが大幅に高速化します。

# IO:DataFileRead
<a name="wait-event.iodatafileread"></a>

`IO:DataFileRead`イベントは、バックエンドプロセスが必要なページを読み込む際に、ページが共有メモリで使用できないため接続が待機したときに発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.iodatafileread.context.supported)
+ [

## Context
](#wait-event.iodatafileread.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.iodatafileread.causes)
+ [

## アクション
](#wait-event.iodatafileread.actions)

## サポート対象エンジンバージョン
<a name="wait-event.iodatafileread.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="wait-event.iodatafileread.context"></a>

すべてのクエリおよびデータ操作 (DML) オペレーションは、バッファプール内のページにアクセスします。読み取りを誘発できるステートメントには、`SELECT`、`UPDATE`、`DELETE`があります。例えば、`UPDATE`は、テーブルまたはインデックスからページを読み取ることができます。要求または更新中のページが共有バッファプールにない場合、この読み取りは`IO:DataFileRead`イベントにつながることがあります。

共有バッファプールは有限のため、いっぱいになる可能性があります。この場合、メモリ上にないページをリクエストすると、データベースは強制的にディスクからブロックを読み取ることになります。`IO:DataFileRead`イベントが頻繁に発生する場合は、共有バッファプールが小さすぎるとワークロードに対応できない可能性があります。この問題は、バッファプールに収まらない多数の行読み取る`SELECT`クエリでは深刻です。バッファプールの詳細については、PostgreSQL ドキュメントの「[リソース消費](https://www.postgresql.org/docs/current/runtime-config-resource.html)」を参照してください。

## 待機時間が増加する原因の可能性
<a name="wait-event.iodatafileread.causes"></a>

`IO:DataFileRead`イベントの一般的な原因は以下のとおりです。

**接続スパイク**  
複数の接続で同じ数の IO:DataFileRead 待機イベントが発生することがあります。この場合、スパイク (突然大きく増加) が `IO:DataFileRead` イベントで発生する可能性があります。

**シーケンシャルスキャンを実行する SELECT および DML ステートメント**  
アプリケーションが新しいオペレーションを実行している可能性があります。または、新しい実行計画のために既存の操作がオペレーションされる可能性があります。このような場合は、`seq_scan`値より大きいテーブル (特に大きなテーブル) を探します。`pg_stat_user_tables`クエリでそれらを探してください。より多くの読み取りオペレーションを生成しているクエリを追跡するには、エクステンション`pg_stat_statements`を使用します。

**大規模なデータセットの CTAS および CREATE INDEX**  
*CTAS*は`CREATE TABLE AS SELECT`ステートメントです。大規模なデータセットを出典として使用して CTAS を実行する場合、または大きなテーブルにインデックスを作成する場合は、`IO:DataFileRead`イベントが発生する可能性があります。インデックスを作成するとき、データベースはシーケンシャルスキャンを使用してオブジェクト全体を読み取る必要があります。CTAS は、ページがメモリ上にないときに`IO:DataFile`リードを生成します。

**複数のバキュームワーカーが同時に実行されている**  
バキュームワーカーは、マニュアルまたは自動でトリガーできます。積極的なバキューム戦略の採用をお勧めします。ただし、テーブルに多数の更新または削除された行がある場合、`IO:DataFileRead`待機が増加します。スペース確保後、`IO:DataFileRead`に費やすバキューム時間が減少します。

**大量データの取り込み**  
アプリケーションで大量のデータを取り込むと、`ANALYZE`オペレーションが頻繁に発生する可能性があります。`ANALYZE`プロセスは、オートバキュームランチャーによって、あるいはマニュアルでトリガーすることができます。  
`ANALYZE`オペレーションは、テーブルのサブセットを読み取ります。30 に`default_statistics_target`値を掛けたものがスキャンを要するページ数です。詳細については、[PostgreSQL ドキュメント](https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-DEFAULT-STATISTICS-TARGET)をご参照ください。`default_statistics_target`パラメータは 1～10,000 の範囲の値を指定でき、デフォルトは 100 です。

**リソースの枯渇**  
インスタンスのネットワーク帯域幅や CPU が消費されると、`IO:DataFileRead`イベントはより頻繁に発生する可能性があります。

## アクション
<a name="wait-event.iodatafileread.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。

**Topics**
+ [

### 待機を生成するクエリの述語フィルターをチェックする
](#wait-event.iodatafileread.actions.filters)
+ [

### メンテナンス作業の影響を最小化する
](#wait-event.iodatafileread.actions.maintenance)
+ [

### 多数の接続に対応する
](#wait-event.iodatafileread.actions.connections)

### 待機を生成するクエリの述語フィルターをチェックする
<a name="wait-event.iodatafileread.actions.filters"></a>

`IO:DataFileRead`待機イベントを生成する特定のクエリを特定するとします。これらは、次の方法を使用して識別できることがあります。
+ Performance Insights
+ エクステンション`pg_stat_statements`で提供されるようなカタログビュー
+ カタログビュー`pg_stat_all_tables`で、定期的な物理読み取り回数の増加を示す場合
+ `pg_statio_all_tables`ビューで、`_read`カウンターの増加が示されている場合

これらのクエリの述語 (`WHERE` 節) でどのフィルターが使用されるかを決定することをお勧めします。次のガイドラインに従ってください:
+ `EXPLAIN` コマンドを実行します。出力では、使用されているスキャンのタイプを特定します。シーケンシャルスキャンは必ずしも問題を示すわけではありません。シーケンシャルスキャンを使用するクエリは、フィルターを使用するクエリと比較して、自然により多くの`IO:DataFileRead`イベントを生成します。

  `WHERE`節に記載された列がインデックスされているかどうかを確認します。されていない場合、この列のインデックスの作成を検討してください。この方法では、シーケンシャルスキャンを回避し、`IO:DataFileRead`イベントの発生を減らすことができます。制限付きフィルターがあってもシーケンシャルスキャンが実行される場合は、適切なインデックスが使用されているかどうかを評価します。
+ クエリが非常に大きなテーブルにアクセスしているかどうかを確認します。場合によっては、テーブルをパーティション化するとクエリで必要なパーティションのみを読み取ることができ、パフォーマンスが向上することがあります。
+ ジョイント操作からカーディナリティ (行の合計数) を検証します。フィルターに渡す`WHERE`節の値がどれほど制限的であるかに注意してください。可能であれば、クエリをチューニングして、計画の各ステップで渡される行数を減らします。

### メンテナンス作業の影響を最小化する
<a name="wait-event.iodatafileread.actions.maintenance"></a>

`VACUUM`や`ANALYZE`のようなメンテナンスオペレーションは重要です。これらのメンテナンス作業に関連する`IO:DataFileRead`待機イベントを見つけても、それらをオフにしないことをお勧めします。次のようなアプローチにより、これらの操作の影響を最小限に抑えることができます。
+ オフピーク時にメンテナンス操作をマニュアルで実行します。この方法では、データベースが自動操作のしきい値に達するのを防ぎます。
+ 非常に大きなテーブルの場合は、テーブルのパーティション化を検討してください。この方法により、メンテナンスオペレーションのオーバーヘッドが削減されます。データベースは、メンテナンスが必要なパーティションにのみアクセスします。
+ 大量のデータを取り込む場合は、自動分析機能を無効にすることを検討してください。

オートバキューム機能は、次の数式が真の場合、テーブルに対して自動的にトリガーされます。

```
pg_stat_user_tables.n_dead_tup > (pg_class.reltuples x autovacuum_vacuum_scale_factor) + autovacuum_vacuum_threshold
```

ビュー`pg_stat_user_tables`とカタログ`pg_class`には複数の行があります。1 行は、テーブル内の 1 つの行に対応できます。この公式は、`reltuples`が特定のテーブル用だと仮定しています。パラメータ `autovacuum_vacuum_scale_factor` (デフォルトは 0.20) と `autovacuum_vacuum_threshold` (デフォルトでは 50 タプル) は通常、インスタンス全体に対してグローバルに設定されます。ただし、特定のテーブルに対して異なる値を設定できます。

**Topics**
+ [

#### 不要な領域を消費しているテーブルを探す
](#wait-event.iodatafileread.actions.maintenance.tables)
+ [

#### 不要な領域を消費しているインデックスを探す
](#wait-event.iodatafileread.actions.maintenance.indexes)
+ [

#### オートバキュームの対象となるテーブルを見つける
](#wait-event.iodatafileread.actions.maintenance.autovacuumed)

#### 不要な領域を消費しているテーブルを探す
<a name="wait-event.iodatafileread.actions.maintenance.tables"></a>

不必要に領域を消費しているテーブルを探すには、PostgreSQL `pgstattuple` 拡張機能の関数を使用できます。この拡張機能 (モジュール) は、すべての RDS for PostgreSQL DB インスタンスにデフォルトで使用でき、次のコマンドを使用してインスタンス化できます。

```
CREATE EXTENSION pgstattuple;
```

この拡張機能の詳細については、PostgreSQL ドキュメントの「[pgstattuple](https://www.postgresql.org/docs/current/pgstattuple.html)」を参照してください。

アプリケーション内のテーブルとインデックスの肥大化をチェックできます。詳細については、「[テーブルとインデックスの肥大化の診断](https://docs.aws.amazon.com//AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.diag-table-ind-bloat.html)」を参照してください。

#### 不要な領域を消費しているインデックスを探す
<a name="wait-event.iodatafileread.actions.maintenance.indexes"></a>

肥大化したインデックスを探し、読み取り権限のあるテーブルで不必要に消費されている領域の大きさを推定するには、次のクエリを実行します。

```
-- WARNING: rows with is_na = 't' are known to have bad statistics ("name" type is not supported).
-- This query is compatible with PostgreSQL 8.2 and later.

SELECT current_database(), nspname AS schemaname, tblname, idxname, bs*(relpages)::bigint AS real_size,
  bs*(relpages-est_pages)::bigint AS extra_size,
  100 * (relpages-est_pages)::float / relpages AS extra_ratio,
  fillfactor, bs*(relpages-est_pages_ff) AS bloat_size,
  100 * (relpages-est_pages_ff)::float / relpages AS bloat_ratio,
  is_na
  -- , 100-(sub.pst).avg_leaf_density, est_pages, index_tuple_hdr_bm, 
  -- maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, sub.reltuples, sub.relpages 
  -- (DEBUG INFO)
FROM (
  SELECT coalesce(1 +
       ceil(reltuples/floor((bs-pageopqdata-pagehdr)/(4+nulldatahdrwidth)::float)), 0 
       -- ItemIdData size + computed avg size of a tuple (nulldatahdrwidth)
    ) AS est_pages,
    coalesce(1 +
       ceil(reltuples/floor((bs-pageopqdata-pagehdr)*fillfactor/(100*(4+nulldatahdrwidth)::float))), 0
    ) AS est_pages_ff,
    bs, nspname, table_oid, tblname, idxname, relpages, fillfactor, is_na
    -- , stattuple.pgstatindex(quote_ident(nspname)||'.'||quote_ident(idxname)) AS pst, 
    -- index_tuple_hdr_bm, maxalign, pagehdr, nulldatawidth, nulldatahdrwidth, reltuples 
    -- (DEBUG INFO)
  FROM (
    SELECT maxalign, bs, nspname, tblname, idxname, reltuples, relpages, relam, table_oid, fillfactor,
      ( index_tuple_hdr_bm +
          maxalign - CASE -- Add padding to the index tuple header to align on MAXALIGN
            WHEN index_tuple_hdr_bm%maxalign = 0 THEN maxalign
            ELSE index_tuple_hdr_bm%maxalign
          END
        + nulldatawidth + maxalign - CASE -- Add padding to the data to align on MAXALIGN
            WHEN nulldatawidth = 0 THEN 0
            WHEN nulldatawidth::integer%maxalign = 0 THEN maxalign
            ELSE nulldatawidth::integer%maxalign
          END
      )::numeric AS nulldatahdrwidth, pagehdr, pageopqdata, is_na
      -- , index_tuple_hdr_bm, nulldatawidth -- (DEBUG INFO)
    FROM (
      SELECT
        i.nspname, i.tblname, i.idxname, i.reltuples, i.relpages, i.relam, a.attrelid AS table_oid,
        current_setting('block_size')::numeric AS bs, fillfactor,
        CASE -- MAXALIGN: 4 on 32bits, 8 on 64bits (and mingw32 ?)
          WHEN version() ~ 'mingw32' OR version() ~ '64-bit|x86_64|ppc64|ia64|amd64' THEN 8
          ELSE 4
        END AS maxalign,
        /* per page header, fixed size: 20 for 7.X, 24 for others */
        24 AS pagehdr,
        /* per page btree opaque data */
        16 AS pageopqdata,
        /* per tuple header: add IndexAttributeBitMapData if some cols are null-able */
        CASE WHEN max(coalesce(s.null_frac,0)) = 0
          THEN 2 -- IndexTupleData size
          ELSE 2 + (( 32 + 8 - 1 ) / 8) 
          -- IndexTupleData size + IndexAttributeBitMapData size ( max num filed per index + 8 - 1 /8)
        END AS index_tuple_hdr_bm,
        /* data len: we remove null values save space using it fractionnal part from stats */
        sum( (1-coalesce(s.null_frac, 0)) * coalesce(s.avg_width, 1024)) AS nulldatawidth,
        max( CASE WHEN a.atttypid = 'pg_catalog.name'::regtype THEN 1 ELSE 0 END ) > 0 AS is_na
      FROM pg_attribute AS a
        JOIN (
          SELECT nspname, tbl.relname AS tblname, idx.relname AS idxname, 
            idx.reltuples, idx.relpages, idx.relam,
            indrelid, indexrelid, indkey::smallint[] AS attnum,
            coalesce(substring(
              array_to_string(idx.reloptions, ' ')
               from 'fillfactor=([0-9]+)')::smallint, 90) AS fillfactor
          FROM pg_index
            JOIN pg_class idx ON idx.oid=pg_index.indexrelid
            JOIN pg_class tbl ON tbl.oid=pg_index.indrelid
            JOIN pg_namespace ON pg_namespace.oid = idx.relnamespace
          WHERE pg_index.indisvalid AND tbl.relkind = 'r' AND idx.relpages > 0
        ) AS i ON a.attrelid = i.indexrelid
        JOIN pg_stats AS s ON s.schemaname = i.nspname
          AND ((s.tablename = i.tblname AND s.attname = pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE)) 
          -- stats from tbl
          OR  (s.tablename = i.idxname AND s.attname = a.attname))
          -- stats from functional cols
        JOIN pg_type AS t ON a.atttypid = t.oid
      WHERE a.attnum > 0
      GROUP BY 1, 2, 3, 4, 5, 6, 7, 8, 9
    ) AS s1
  ) AS s2
    JOIN pg_am am ON s2.relam = am.oid WHERE am.amname = 'btree'
) AS sub
-- WHERE NOT is_na
ORDER BY 2,3,4;
```

#### オートバキュームの対象となるテーブルを見つける
<a name="wait-event.iodatafileread.actions.maintenance.autovacuumed"></a>

自動バキュームの対象となるテーブルを見つけるには、次のクエリを実行します。

```
--This query shows tables that need vacuuming and are eligible candidates.
--The following query lists all tables that are due to be processed by autovacuum. 
-- During normal operation, this query should return very little.
WITH  vbt AS (SELECT setting AS autovacuum_vacuum_threshold 
              FROM pg_settings WHERE name = 'autovacuum_vacuum_threshold')
    , vsf AS (SELECT setting AS autovacuum_vacuum_scale_factor 
              FROM pg_settings WHERE name = 'autovacuum_vacuum_scale_factor')
    , fma AS (SELECT setting AS autovacuum_freeze_max_age 
              FROM pg_settings WHERE name = 'autovacuum_freeze_max_age')
    , sto AS (SELECT opt_oid, split_part(setting, '=', 1) as param, 
                split_part(setting, '=', 2) as value 
              FROM (SELECT oid opt_oid, unnest(reloptions) setting FROM pg_class) opt)
SELECT
    '"'||ns.nspname||'"."'||c.relname||'"' as relation
    , pg_size_pretty(pg_table_size(c.oid)) as table_size
    , age(relfrozenxid) as xid_age
    , coalesce(cfma.value::float, autovacuum_freeze_max_age::float) autovacuum_freeze_max_age
    , (coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + 
         coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples) 
         as autovacuum_vacuum_tuples
    , n_dead_tup as dead_tuples
FROM pg_class c 
JOIN pg_namespace ns ON ns.oid = c.relnamespace
JOIN pg_stat_all_tables stat ON stat.relid = c.oid
JOIN vbt on (1=1) 
JOIN vsf ON (1=1) 
JOIN fma on (1=1)
LEFT JOIN sto cvbt ON cvbt.param = 'autovacuum_vacuum_threshold' AND c.oid = cvbt.opt_oid
LEFT JOIN sto cvsf ON cvsf.param = 'autovacuum_vacuum_scale_factor' AND c.oid = cvsf.opt_oid
LEFT JOIN sto cfma ON cfma.param = 'autovacuum_freeze_max_age' AND c.oid = cfma.opt_oid
WHERE c.relkind = 'r' 
AND nspname <> 'pg_catalog'
AND (
    age(relfrozenxid) >= coalesce(cfma.value::float, autovacuum_freeze_max_age::float)
    or
    coalesce(cvbt.value::float, autovacuum_vacuum_threshold::float) + 
      coalesce(cvsf.value::float,autovacuum_vacuum_scale_factor::float) * c.reltuples <= n_dead_tup
    -- or 1 = 1
)
ORDER BY age(relfrozenxid) DESC;
```

### 多数の接続に対応する
<a name="wait-event.iodatafileread.actions.connections"></a>

Amazon CloudWatch をモニタリングすると、`DatabaseConnections`メトリックスパイクが見つかることがあります。この増加は、データベースへの接続数が増加していることを示します。次のようなアプローチを推奨します。
+ アプリケーションが各インスタンスで開くことができる接続の数を制限します。アプリケーションが組み込み接続プール機能を備えている場合は、適切な数の接続を設定します。インスタンス内の vCPUs が効果的にパラレル化できる数値を基準にします。

  アプリケーションで接続プール機能を使用しない場合は、Amazon RDS プロキシまたは代替の使用を検討してください。このアプローチにより、アプリケーションはロードバランサーとの複数の接続を開くことができます。その後、バランサーは、データベースとの制限された数の接続を開くことができます。パラレルで実行される接続が少なくなると、DB インスタンスのカーネル内のコンテキスト切り替えが減少します。クエリの進行が速くなり、待機イベントが減少するはずです。詳細については、「[Amazon RDS Proxy ](rds-proxy.md)」を参照してください。
+ 可能であれば、RDS for PostgreSQL のリードレプリカを活用してください。アプリケーションが読み取り専用のオペレーションを実行するときは、これらのリクエストを読み取り専用レプリカに送信します。この方法でプライマリ (ライター) ノードの I/O 負荷を軽減します。
+ DB インスタンスのスケールアップを検討します。大容量のインスタンスクラスはより多くのメモリを提供するため、RDS for PostgreSQL ではページを保持するためのより大きな共有バッファプールを提供します。サイズが大きければ、DB インスタンスが接続処理する vCPUs も多くなります。特に、`IO:DataFileRead`待機イベントを発生させているオペレーションが書き込みの場合、vCPU の増設は有効です。

# IO:WALWrite
<a name="wait-event.iowalwrite"></a>



**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.iowalwrite.context.supported)
+ [

## Context
](#wait-event.iowalwrite.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.iowalwrite.causes)
+ [

## アクション
](#wait-event.iowalwrite.actions)

## サポート対象エンジンバージョン
<a name="wait-event.iowalwrite.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL 10 以降のすべてのバージョンでサポートされています。

## Context
<a name="wait-event.iowalwrite.context"></a>

先行書き込みログデータを生成しているデータベース内のアクティビティは、最初に WAL バッファをいっぱいにし、次に非同期でディスクに書き込みます。待機イベント `IO:WALWrite` は、トランザクションの COMMIT 呼び出しを解放できるように、WAL データのディスクへの書き込みが完了するまで SQL セッションの待機中に生成されます。

## 待機時間が増加する原因の可能性
<a name="wait-event.iowalwrite.causes"></a>

この待機イベントが頻繁に発生する場合は、ワークロードが実行する更新の種類とその頻度を確認する必要があります。特に、次のタイプのアクティビティを確認します。

**高負荷の DML アクティビティ**  
データベーステーブルのデータは、すぐに変更されるわけではありません。あるテーブルへの挿入は、別のクライアントからの同じテーブルへの挿入または更新を待つ必要がある場合があります。データ操作言語 (DML) のステートメントによってデータ値 (INSERT、UPDATE、DELETE、COMMIT、ROLLBACK TRANSACTION) を変更したことで競合が発生し、先行書き込みログファイルがバッファのフラッシュを待つ可能性があります。この状況は、以下の Amazon RDS Performance Insights メトリクスにも表れており、高負荷の DML アクティビティを示しています。  
+  `tup_inserted`
+ `tup_updated`
+ `tup_deleted`
+ `xact_rollback`
+ `xact_commit`
これらのメトリクスの詳細については、「[Amazon RDS for PostgreSQL の Performance Insights カウンター](USER_PerfInsights_Counters.md#USER_PerfInsights_Counters.PostgreSQL)」を参照してください。

**チェックポイントアクティビティの頻度**  
チェックポイントが頻繁に発生すると、WAL ファイルの数が増えます。RDS for PostgreSQL では、ページ全体の書き込みは常に「オン」になっています。ページ全体への書き込みは、データ損失の防止に役立ちます。ただし、チェックポイントが頻繁に行われると、システム全体のパフォーマンスの問題が発生することがあります。これは、特に 高負荷の DML アクティビティのシステムに当てはまります。場合によっては、`postgresql.log` に「チェックポイントが頻繁に発生しています」というエラーメッセージが表示されることがあります。  
チェックポイントをチューニングする際には、異常なシャットダウンが発生した場合に予想される復旧時間と、パフォーマンスとのバランスを慎重に取ることをお勧めします。

## アクション
<a name="wait-event.iowalwrite.actions"></a>

この待機イベントの数を削減するには、次のアクションをお勧めします。

**Topics**
+ [

### コミットの回数を減らす
](#wait-event.iowalwrite.actions.problem)
+ [

### チェックポイントのモニタリング
](#wait-event.iowalwrite.actions.monitor)
+ [

### IO のスケールアップ
](#wait-event.iowalwrite.actions.scale-io)
+ [

### 専用ログボリューム (DLV)
](#wait-event.iowalwrite.actions.dlv)

### コミットの回数を減らす
<a name="wait-event.iowalwrite.actions.problem"></a>

コミット数を減らすには、ステートメントをトランザクションブロックにまとめることができます。Amazon RDS Performance Insights を使用して、実行されているクエリの種類を確認してください。また、大規模なメンテナンスオペレーションをオフピークの時間帯に移動することもできます。例えば、インデックスを作成したり、稼働時間外に `pg_repack` オペレーションを使用したりします。

### チェックポイントのモニタリング
<a name="wait-event.iowalwrite.actions.monitor"></a>

RDS for PostgreSQL DB インスタンスがチェックポイント用に WAL ファイルに書き込む頻度をモニタリングできるパラメータが 2 つあります。
+ `log_checkpoints` – このパラメータはデフォルトで「オン」になっています。これにより、チェックポイントごとにメッセージが PostgreSQL ログに送信されます。これらのログメッセージには、書き込まれたバッファの数、書き込みにかかった時間、特定のチェックポイントで追加、削除、またはリサイクルされた WAL ファイルの数が含まれます。

  このパラメータについての詳細は、PostgreSQL ドキュメントの「[エラー報告とログ記録](https://www.postgresql.org/docs/current/runtime-config-logging.html#GUC-LOG-CHECKPOINTS)」を参照してください。
+ `checkpoint_warning` – このパラメータは、チェックポイント頻度のしきい値 (秒単位) を設定します。この値を超えると、警告が表示されます。デフォルトでは、このパラメータは RDS for PostgreSQL では設定されていません。このパラメータの値を設定すると、RDS for PostgreSQL DB インスタンスのデータベース変更が WAL ファイルのサイズが処理できない速度で書き込まれたときに警告を受け取ることができます。例えば、このパラメータを 30 に設定したとします。RDS for PostgreSQL インスタンスが 30 秒に 1 回以上の頻度で変更を書き込む必要がある場合、「チェックポイントが頻繁に発生しています」という警告が PostgreSQL ログに送信されます。これは、`max_wal_size` 値を増やす必要があることを示している可能性があります。

  詳細については、PostgreSQL ドキュメントの「[ログ先行書き込み](https://www.postgresql.org/docs/current/runtime-config-wal.html#RUNTIME-CONFIG-WAL-CHECKPOINTS)」を参照してください。

### IO のスケールアップ
<a name="wait-event.iowalwrite.actions.scale-io"></a>

このタイプの入出力 (IO) 待機イベントは、1 秒あたりの入出力オペレーション (IOPS) をスケーリングして IO を高速化することで修正できます。CPU をスケーリングするよりも IO をスケーリングする方が望ましいです。CPU をスケーリングすると、処理量が増えることで IO ボトルネックがさらに悪化するため、IO の競合がさらに増える可能性があります。一般的に、スケーリングを実行する前にワークロードのチューニングを検討することをお勧めします。

### 専用ログボリューム (DLV)
<a name="wait-event.iowalwrite.actions.dlv"></a>

Amazon RDS コンソール、AWS CLI、または Amazon RDS API を使用して、プロビジョンド IOPS (PIOPS) ストレージを使用する DB インスタンスの専用ログボリューム (DLV) を使用できます。DLV は、PostgreSQL データベーストランザクションログを、データベーステーブルを含むボリュームとは別のストレージボリュームに移動します。詳細については、「[専用ログボリューム (DLV)](CHAP_Storage.md#CHAP_Storage.dlv)」を参照してください。

# IPC:parallel 待機イベント
<a name="rpg-ipc-parallel"></a>

以下の `IPC:parallel wait events` は、セッションが並列クエリ実行オペレーションに関連するプロセス間通信を待機していることを示します。
+ `IPC:BgWorkerStartup` - プロセスは、並列ワーカープロセスが起動シーケンスを完了するのを待機しています。これは、並列クエリ実行のためにワーカーを初期化するときに発生します。
+ `IPC:BgWorkerShutdown` - プロセスは、並列ワーカープロセスがシャットダウンシーケンスを完了するのを待機しています。これは、並列クエリ実行のクリーンアップフェーズ中に発生します。
+ `IPC:ExecuteGather` - プロセスは、クエリの実行中に並列ワーカープロセスからデータを受信するのを待機しています。これは、リーダープロセスがワーカーから結果を収集する必要がある場合に発生します。
+ `IPC:ParallelFinish` - プロセスは、並列ワーカーが実行を終了して最終結果を報告するのを待機しています。これは、並列クエリ実行の完了フェーズ中に発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#rpg-ipc-parallel-context-supported)
+ [

## Context
](#rpg-ipc-parallel-context)
+ [

## 待機時間が増加する原因の可能性
](#rpg-ipc-parallel-causes)
+ [

## アクション
](#rpg-ipc-parallel-actions)

## サポート対象エンジンバージョン
<a name="rpg-ipc-parallel-context-supported"></a>

この待機イベント情報は、Aurora PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="rpg-ipc-parallel-context"></a>

PostgreSQL での並列クエリの実行では、複数のプロセスが連携して単一のクエリを処理します。クエリが並列化に適していると判断されると、リーダープロセスは `max_parallel_workers_per_gather` パラメータ設定に基づいて 1 つ以上の並列ワーカープロセスと連携します。リーダープロセスはワーカー間に作業を分割し、各ワーカーは担当するデータ部分を個別に処理します。結果はリーダープロセスに収集されます。

**注記**  
各並列ワーカーは、フルユーザーセッションと同様のリソース要件を持つ個別のプロセスとして動作します。並列クエリで 4 つのワーカーが連携する場合、リーダープロセスと各ワーカープロセスの両方が独自のリソース割り当てを維持するため、非並列クエリと比較してリソース (CPU、メモリ、I/O 帯域幅) を最大 5 倍消費する可能性があります。例えば、`work_mem` のような設定は各ワーカーに個別に適用されるため、すべてのプロセスにわたって合計メモリ使用量が乗算される可能性があります。

並列クエリアーキテクチャは、以下の 3 つの主要コンポーネントで構成されます。
+ リーダープロセス: 並列オペレーションを開始して、ワークロードを分割し、ワーカープロセスと連携するメインプロセス。
+ ワーカープロセス: クエリの一部を並行して実行するバックグラウンドプロセス。
+ ギャザー/ギャザーマージ: 複数のワーカープロセスの結果をリーダーに戻してまとめるオペレーション。

並列実行中、プロセスはプロセス間通信 (IPC) メカニズムを介して相互に通信する必要があります。これらの IPC 待機イベントは、以下のさまざまなフェーズで発生します。
+ ワーカーの起動: 並列ワーカーを初期化するとき
+ データ交換: ワーカーがデータを処理し、結果をリーダーに送信するとき
+ ワーカーのシャットダウン: 並列実行が完了し、ワーカーを終了するとき
+ 同期ポイント: プロセス間で連携する必要があるとき、または他のプロセスがタスクを完了するまで待機する必要があるとき

これらの待機イベントを理解することは、特に複数の並列クエリが同時に実行中となる可能性が高い同時実行環境において、並列クエリの実行に関連するパフォーマンスの問題を診断するために重要です。

## 待機時間が増加する原因の可能性
<a name="rpg-ipc-parallel-causes"></a>

並列関連の IPC 待機イベントの増加には、いくつかの要因が関係します。

**並列クエリに伴う高い同時実行性**  
多数の並列クエリを同時に実行すると、リソースの競合が発生し、IPC オペレーションの待機時間が長くなる可能性があります。これは、トランザクション量が多いシステムや分析ワークロードで特によく見られます。

**最適ではない並列クエリプラン**  
クエリプランナーで非効率的な並列プランを選択すると、ワーカー間での不要な並列化や作業分散の低下につながる可能性があります。その結果、特に `IPC:ExecuteGather` イベントと `IPC:ParallelFinish` イベントで、IPC 待機時間が長くなることがあります。こうしたプランニングの問題は、多くの場合、古い統計情報やテーブル/インデックスの肥大化が原因です。

**並列ワーカーの頻繁な起動とシャットダウン**  
有効期間の短いクエリによる並列ワーカーの頻繁な開始と終了は、`IPC:BgWorkerStartup` イベントと `IPC:BgWorkerShutdown` イベントの増加につながる可能性があります。これは、多くの小さな並列化可能なクエリを含む OLTP ワークロードでよく見られます。

**リソースの制約**  
CPU、メモリ、または I/O 容量が制限されると、並列実行でボトルネックが発生し、すべての IPC イベントで待機時間が長くなる可能性があります。例えば、CPU が飽和していると、ワーカープロセスが作業の一部を起動または処理するのに時間がかかることがあります。

**複雑なクエリ構造**  
複数レベルの並列処理 (並列結合の後に並列集約が続くなど) を含むクエリは、特に `IPC:ExecuteGather` イベントの場合、IPC パターンが複雑化し、待機時間が長くなる可能性があります。

**大きな結果セット**  
結果セットが大きいクエリでは、リーダープロセスがワーカープロセスからの結果の収集と処理により多くの時間を費やすため、`IPC:ExecuteGather` の待機時間が長くなる可能性があります。

これらの要因を理解することは、Aurora PostgreSQL での並列クエリ実行に関連するパフォーマンスの問題の診断と対処に役立ちます。

## アクション
<a name="rpg-ipc-parallel-actions"></a>

並列クエリに関連する待機が生じた場合は、通常、バックエンドプロセスが並列ワーカープロセスを連携中または待機中であることを意味します。これらの待機は、並列プランの実行中によく発生します。これらの待機の影響を調査して軽減するには、並列ワーカーの使用状況をモニタリングし、パラメータ設定を見直して、クエリの実行とリソース割り当てを調整します。

**Topics**
+ [

### 非効率的な並列処理のクエリプランを分析する
](#rpg-ipc-parallel-analyze-plans)
+ [

### 並列クエリの使用状況をモニタリングする
](#rpg-ipc-parallel-monitor)
+ [

### 並列クエリ設定を確認して調整する
](#rpg-ipc-parallel-adjust-settings)
+ [

### リソース割り当てを最適化する
](#rpg-ipc-parallel-optimize-resources)
+ [

### 接続管理を調査する
](#rpg-ipc-parallel-connection-management)
+ [

### メンテナンスオペレーションを確認して最適化する
](#rpg-ipc-parallel-maintenance)

### 非効率的な並列処理のクエリプランを分析する
<a name="rpg-ipc-parallel-analyze-plans"></a>

並列クエリを実行すると、システムの不安定性、CPU 使用率の急上昇、予測不可能なクエリパフォーマンスの変動が発生しがちです。並列処理によって特定のワークロードが実際に改善されるかどうかを徹底的に分析することが重要です。EXPLAIN ANALYZE を使用して、並列クエリ実行プランを確認してください。

プランの効率を比較するには、セッションレベルで並列処理を一時的に無効にします。

```
SET max_parallel_workers_per_gather = 0;
EXPLAIN ANALYZE <your_query>;
```

並列処理を再度有効にして比較します。

```
RESET max_parallel_workers_per_gather;
EXPLAIN ANALYZE <your_query>;
```

並列処理を無効にすると、より良い結果またはより一貫した結果が得られる場合は、SET コマンドを使用してセッションレベルで特定のクエリに対して並列処理を無効にすることを検討してください。より広範な効果を得るには、DB パラメータグループの関連するパラメータを調整して、インスタンスレベルで並列処理を無効にすることもできます。詳細については、「[Amazon RDS の DB パラメータグループのパラメータの変更](USER_WorkingWithParamGroups.Modifying.md)」を参照してください。

### 並列クエリの使用状況をモニタリングする
<a name="rpg-ipc-parallel-monitor"></a>

以下のクエリを使用して、並列クエリのアクティビティと容量を可視化します。

アクティブな並列ワーカープロセスを確認します。

```
SELECT
    COUNT(*)
FROM
    pg_stat_activity
WHERE
    backend_type = 'parallel worker';
```

このクエリは、アクティブな並列ワーカープロセスの数を示します。値が高い場合は、`max\$1parallel\$1workers` の設定値が高い可能性があるため、値を下げることを検討できます。

同時並列クエリを確認します。

```
SELECT
    COUNT(DISTINCT leader_pid)
FROM
    pg_stat_activity
WHERE
    leader_pid IS NOT NULL;
```

このクエリは、並列クエリを起動した個別のリーダープロセスの数を返します。ここで数値が高い場合は、複数のセッションで並列クエリを同時に実行中であることを示しているため、CPU とメモリの需要が増加する可能性があります。

### 並列クエリ設定を確認して調整する
<a name="rpg-ipc-parallel-adjust-settings"></a>

以下のパラメータがワークロードに適合していることを確認します。
+ `max_parallel_workers`: すべてのセッションにわたる並列ワーカーの合計数。
+ `max_parallel_workers_per_gather`: クエリあたりの最大ワーカー数。

OLAP ワークロードの場合、これらの値を増やすと、パフォーマンスが向上する可能性があります。OLTP ワークロードの場合は、一般的に値を低く設定することが推奨されます。

```
SHOW max_parallel_workers;
SHOW max_parallel_workers_per_gather;
```

### リソース割り当てを最適化する
<a name="rpg-ipc-parallel-optimize-resources"></a>

CPU 使用率をモニタリングし、値が一貫して高い場合や、アプリケーションが並列クエリのメリットを得られる場合は、vCPU の数を調整することを検討してください。並列オペレーションに十分なメモリが使用可能であることを確認します。
+ Performance Insights メトリクスを使用して、システムが CPU の処理能力に制約されているかどうかを判断します。
+ 各並列ワーカーは独自の `work_mem` を使用します。合計メモリ使用量がインスタンスの制限内であることを確認します。

並列クエリは、非並列クエリよりもかなり多くのリソースを消費する可能性があります。各ワーカープロセスは完全に独立したプロセスであり、別のユーザーセッションを追加するのとほぼ同じ影響をシステムにもたらすためです。この設定の値を選択したり、リソース使用率を制御する他の設定 (`work_mem` など) を構成したりする場合は、この点を考慮に入れる必要があります。詳細については、[PostgreSQL ドキュメント](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-WORK-MEM)をご参照ください。`work_mem` などのリソース制限は各ワーカーに個別に適用されるため、すべてのプロセスにわたる合計使用率は、単一のプロセスにおける通常の使用率よりも大幅に高くなる可能性があります。

ワークロードを高度に並列化する場合は、vCPU を増やすか、メモリパラメータを調整することを検討してください。

### 接続管理を調査する
<a name="rpg-ipc-parallel-connection-management"></a>

接続が不足している場合は、アプリケーション接続プーリング戦略を見直します。接続プーリングをまだ使用していない場合は、アプリケーションレベルで実装することを検討してください。

### メンテナンスオペレーションを確認して最適化する
<a name="rpg-ipc-parallel-maintenance"></a>

インデックスの作成やその他のメンテナンスタスクを調整して、リソースの競合を防ぎます。これらのオペレーションは、オフピーク時間帯にスケジュールすることを検討してください。ユーザークエリの負荷が高い間は、負荷の高いメンテナンス (並列インデックスのビルドなど) をスケジュールしないでください。これらのオペレーションは並列ワーカーを消費し、通常のクエリのパフォーマンスに影響を与える可能性があります。

# IPC:ProcArrayGroupUpdate
<a name="apg-rpg-ipcprocarraygroup"></a>

`IPC:ProcArrayGroupUpdate` イベントは、セッションが、グループリーダーによるオペレーション終了時のトランザクションステータスの更新を待機しているときに発生します。PostgreSQL は通常、IPC タイプの待機イベントを並列クエリオペレーションに関連付けますが、この特定の待機イベントは並列クエリに固有ではありません。

**Topics**
+ [

## サポート対象エンジンバージョン
](#apg-rpg-ipcprocarraygroup.supported)
+ [

## Context
](#apg-rpg-ipcprocarraygroup.context)
+ [

## 待機時間が増加する原因の可能性
](#apg-rpg-ipcprocarraygroup.causes)
+ [

## アクション
](#apg-rpg-ipcprocarraygroup.actions)

## サポート対象エンジンバージョン
<a name="apg-rpg-ipcprocarraygroup.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="apg-rpg-ipcprocarraygroup.context"></a>

**プロセス配列の理解** – プロセス (proc) 配列は PostgreSQL の共有メモリ構造です。トランザクションの詳細など、実行中のすべてのプロセスに関する情報を保持します。トランザクションの完了時 (`COMMIT` または `ROLLBACK`) に、ProcArray を更新して変更を反映し、配列から transactionID をクリアする必要があります。トランザクションを完了しようとするセッションは、ProcArray で排他的ロックを取得する必要があります。これにより、他のプロセスが共有ロックまたは排他的ロックを取得できなくなります。

**グループ更新メカニズム** – COMMIT または ROLLBACK の実行中に、バックエンドプロセスが排他的モードで ProcArrayLock を取得できない場合、ProcArrayGroupMember という特別なフィールドを更新します。これにより、終了する予定のセッションのリストにトランザクションが追加されます。このバックエンドプロセスはスリープし、スリープ時間は ProcArrayGroupUpdate 待機イベントとして計測されます。procArrayGroupMember を使用した ProcArray の最初のプロセスはリーダープロセスと呼ばれ、ProcArrayLock を排他的モードで取得します。次に、グループ transactionID のクリアを待機しているプロセスのリストをクリアします。これが完了すると、リーダーは ProcArrayLock をリリースし、このリストのすべてのプロセスを起動して、トランザクションが完了したことを通知します。

## 待機時間が増加する原因の可能性
<a name="apg-rpg-ipcprocarraygroup.causes"></a>

実行中のプロセスが多いほど、リーダーが排他的モードで procArrayLock を保持する時間が長くなります。したがって、グループ更新シナリオでより多くの書き込みトランザクションが発生すると、`ProcArrayGroupUpdate` 待機イベントを待っているプロセスが蓄積される可能性があります。Database Insights のトップ SQL ビューでは、COMMIT がこの待機イベントの大部分を持つステートメントであることがわかります。これは予想される動作ですが、実行する特定の書き込み SQL をより詳細に調査して、実行する適切なアクションを決定する必要があります。

## アクション
<a name="apg-rpg-ipcprocarraygroup.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。Amazon RDS Performance Insights を使用するか、PostgreSQL システムビュー `pg_stat_activity` をクエリして、`IPC:ProcArrayGroupUpdate` イベントを特定します。

**Topics**
+ [

### トランザクションコミットおよびロールバックオペレーションのモニタリング
](#apg-rpg-ipcprocarraygroup.actions.monitor)
+ [

### 同時実行数の削減
](#apg-rpg-ipcprocarraygroup.actions.concurrency)
+ [

### 接続プーリングを実装する
](#apg-rpg-ipcprocarraygroup.actions.pooling)
+ [

### 高速ストレージの使用
](#apg-rpg-ipcprocarraygroup.actions.storage)

### トランザクションコミットおよびロールバックオペレーションのモニタリング
<a name="apg-rpg-ipcprocarraygroup.actions.monitor"></a>

**コミットとロールバックのモニタリング** – コミットとロールバックの数が増えると、ProcArray への負荷が増大する可能性があります。例えば、重複するキー違反の増加が原因で SQL ステートメントが失敗し始めた場合、ロールバックが増加し、ProcArray の競合とテーブルの肥大化が増加する可能性があります。

Amazon RDS Database Insights は PostgreSQL メトリクス `xact_commit` と `xact_rollback` を提供し、1 秒あたりのコミット数とロールバック数を報告します。

### 同時実行数の削減
<a name="apg-rpg-ipcprocarraygroup.actions.concurrency"></a>

**トランザクションのバッチ処理** – 可能であれば、コミット/ロールバック操作を減らすために、単一のトランザクションでバッチ操作を行います。

**同時実行数の制限** – ProcArray でのロック競合を軽減するために、同時にアクティブなトランザクションの数を減らします。ある程度のテストが必要になりますが、同時接続の合計数を減らすと、競合を減らし、スループットを維持できます。

### 接続プーリングを実装する
<a name="apg-rpg-ipcprocarraygroup.actions.pooling"></a>

**接続プーリングソリューション** – 接続プーリングを使用してデータベース接続を効率的に管理し、バックエンドの合計数を減らし、ProcArray のワークロードを削減します。ある程度のテストが必要になりますが、同時接続の合計数を減らすと、競合を減らし、スループットを維持できます。

**接続ストームの軽減** – 同様に、頻繁に接続を作成および終了するパターンにより、ProcArray にさらなる負荷がかかります。このパターンを減らすことで、全体的な競合が軽減されます。

### 高速ストレージの使用
<a name="apg-rpg-ipcprocarraygroup.actions.storage"></a>

**専用ログボリューム** – `IPC:ProcArrayGroupUpdate` 待機イベントに高い `IO:WALWrite` 待機イベントが伴う場合、専用ログボリュームを設定すると、WAL への書き込みのボトルネックを減らすことができます。これにより、コミットのパフォーマンスが向上します。

詳細については、「[専用ログボリューム](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PIOPS.dlv.html)」を参照してください。

# Lock:advisory
<a name="wait-event.lockadvisory"></a>

`Lock:advisory`イベントは、PostgreSQL アプリケーションがロックを使用して複数のセッション全体のアクティビティを調整するときに発生します。

**Topics**
+ [

## 関連するエンジンのバージョン
](#wait-event.lockadvisory.context.supported)
+ [

## Context
](#wait-event.lockadvisory.context)
+ [

## 原因
](#wait-event.lockadvisory.causes)
+ [

## アクション
](#wait-event.lockadvisory.actions)

## 関連するエンジンのバージョン
<a name="wait-event.lockadvisory.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL バージョン 9.6 以降に関連します。

## Context
<a name="wait-event.lockadvisory.context"></a>

PostgreSQL アドバイザリロックは、ユーザーのアプリケーションコードによって明示的にロックおよびロック解除を実行するアプリケーションレベルの協調的ロックです。アプリケーションは PostgreSQL アドバイザリロックを使用して、複数のセッションにまたがるアクティビティを調整できます。通常のオブジェクトレベルまたは行レベルのロックとは異なり、アプリケーションはロックのライフタイムを完全に制御できます。詳細については、PostgreSQL ドキュメントの [Advisory Locks (アドバイザリロック)](https://www.postgresql.org/docs/12/explicit-locking.html#ADVISORY-LOCKS) を参照してください。

アドバイザリロックは、トランザクションが終了する前に解放されるか、トランザクション間のセッションで保持されます。これは、`CREATE INDEX`ステートメントによって取得されたテーブルへのアクセス排他ロックなど、暗黙のうちにシステムで強制されるロックには当てはまりません。

アドバイザリロックの取得 (ロック) およびリリース (ロック解除) に使用される関数の説明については、「PostgreSQL のドキュメント」の[アドバイザリロックの関数](https://www.postgresql.org/docs/current/functions-admin.html#FUNCTIONS-ADVISORY-LOCKS)を参照してください。

アドバイザリロックは、通常の PostgreSQL ロックシステムの上に実装され、`pg_locks`システムビューで表示できます。

## 原因
<a name="wait-event.lockadvisory.causes"></a>

このロックタイプは、明示的に使用するアプリケーションによって排他的に制御されます。クエリの一部として各行に対して取得されるアドバイザリロックは、ロックの急増や、長期的な蓄積を引き起こすことがあります。

これらの効果は、クエリが返すよりも多くの行でロックを取得する方法でクエリが実行されると発生します。アプリケーションは最終的にすべてのロックを解放する必要がありますが、返されない行でロックが取得された場合、アプリケーションはすべてのロックを見つけることができません。

PostgreSQL のドキュメントの「[アドバイザリロック](https://www.postgresql.org/docs/12/explicit-locking.html#ADVISORY-LOCKS)」からの例を紹介します。

```
SELECT pg_advisory_lock(id) FROM foo WHERE id > 12345 LIMIT 100;
```

この例では、`LIMIT`節がクエリの出力を停止できるのは、内部で行が選択され、その ID 値がロックされた後のみです。これは、データ量の増加により、プランナーが開発中にテストされなかった別の実行プランを選択した場合に突然発生することがあります。この場合の構築アップは、アプリケーションがロックされた各ID値に明示的に`pg_advisory_unlock`を呼び出すことによって発生します。ただし、この場合、返されなかった行において取得されたロックのセットを見つけることはできません。ロックはセッションレベルで取得されるため、トランザクションの終了時に自動的に解放されません。

ブロックされたロック試行のスパイクは、意図しない競合が原因の可能性があります。このような競合では、アプリケーションの無関係な部分が、誤って同じロック ID スペースを共有します。

## アクション
<a name="wait-event.lockadvisory.actions"></a>

アドバイザリロックのアプリケーション使用状況を確認し、アプリケーションフロー内のいつどこで各タイプのアドバイザリロックが取得および解放されるのか、詳しく説明します。

セッションが取得したロックが多すぎるか、長時間実行しているセッションがロックを早期に解放しないために、ロックの蓄積が遅くなっているかどうかを調べます。`pg_terminate_backend(pid)`を使用してセッションを終了すると、セッションレベルロックの遅い蓄積を修正できます。

アドバイザリロックを待機中のクライアントが`pg_stat_activity`、`wait_event_type=Lock`、`wait_event=advisory`に表示されます。同じ`pid`の`pg_locks`システムビューへのクエリを実行し、`locktype=advisory`と`granted=f`を検索することで、特定のロック値を取得できます。

`pg_locks`に対して`granted=t`を持つ同じアドバイザリロックへのクエリを実行することで、ブロックしているセッションを特定することができます。

```
SELECT blocked_locks.pid AS blocked_pid,
         blocking_locks.pid AS blocking_pid,
         blocked_activity.usename AS blocked_user,
         blocking_activity.usename AS blocking_user,
         now() - blocked_activity.xact_start AS blocked_transaction_duration,
         now() - blocking_activity.xact_start AS blocking_transaction_duration,
         concat(blocked_activity.wait_event_type,':',blocked_activity.wait_event) AS blocked_wait_event,
         concat(blocking_activity.wait_event_type,':',blocking_activity.wait_event) AS blocking_wait_event,
         blocked_activity.state AS blocked_state,
         blocking_activity.state AS blocking_state,
         blocked_locks.locktype AS blocked_locktype,
         blocking_locks.locktype AS blocking_locktype,
         blocked_activity.query AS blocked_statement,
         blocking_activity.query AS blocking_statement
    FROM pg_catalog.pg_locks blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks blocking_locks
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
    WHERE NOT blocked_locks.GRANTED;
```

すべてのアドバイザリロック API 関数には、1 つの`bigint`引数または2つの`integer`引数の 2 組の引数があります。
+ `bigint` の引数が 1 つの API 関数では、上位 32 ビットが `pg_locks.classid`、下位 32 ビットが `pg_locks.objid` となります。
+ `integer`が2つある API 関数の場合、第 1 引数は`pg_locks.classid`、第 2 引数は`pg_locks.objid`となります。

`pg_locks.objsubid`値はどの API フォームが使用されたかを示し、`1`は 1 つの`bigint`引数、`2`は 2 つの`integer`引数を意味します。

# Lock:extend
<a name="wait-event.lockextend"></a>

`Lock:extend`イベントは、バックエンドプロセスがリレーションを拡張するためにロックするのを待っているときに、別のプロセスが同じ目的でそのリレーションをロックしていると発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.lockextend.context.supported)
+ [

## Context
](#wait-event.lockextend.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.lockextend.causes)
+ [

## アクション
](#wait-event.lockextend.actions)

## サポート対象エンジンバージョン
<a name="wait-event.lockextend.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="wait-event.lockextend.context"></a>

イベント`Lock:extend`は、バックエンドプロセスがリレーションの拡張する間、他のバックエンドプロセスがそのリレーションを拡張するのを待っている間にロックを保持することを示しています。リレーションを拡張できるのは一度に 1 つのプロセスだけなので、システムは`Lock:extend`待機イベントを発生させます。`INSERT`、`COPY`、`UPDATE`のオペレーションでこのイベントを生成することができます。

## 待機時間が増加する原因の可能性
<a name="wait-event.lockextend.causes"></a>

`Lock:extend`イベントが通常より頻繁に発生する場合は、パフォーマンスの問題を示していることがあります。典型的な原因は次のとおりです。

**同じテーブルへの同時挿入または更新の急増 **  
同じテーブルに挿入または更新するクエリの同時セッションが増加する可能性があります。

**ネットワーク帯域幅の不足**  
DB インスタンスのネットワーク帯域幅が、現在のワークロードのストレージ通信ニーズに対して不十分な可能性があります。これは、`Lock:extend`イベントの増加を引き起こすストレージレイテンシーの原因となることがあります。

## アクション
<a name="wait-event.lockextend.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。

**Topics**
+ [

### 同じリレーションへの同時挿入と更新を減らす
](#wait-event.lockextend.actions.action1)
+ [

### ネットワーク帯域幅の増加
](#wait-event.lockextend.actions.increase-network-bandwidth)

### 同じリレーションへの同時挿入と更新を減らす
<a name="wait-event.lockextend.actions.action1"></a>

まず、`tup_inserted`、`tup_updated`メトリクスの増加と、それに伴うこの待機イベントの増加があるかどうか判断します。その場合は、挿入および更新オペレーションで競合性が高いリレーションをチェックします。これを判断するには、`n_tup_ins`および`n_tup_upd`フィールドでの値の`pg_stat_all_tables`ビューへのクエリを実行します。`pg_stat_all_tables`ビューの詳細については、PostgreSQL ドキュメントの「[pg\$1stat\$1statements](https://www.postgresql.org/docs/13/monitoring-stats.html#MONITORING-PG-STAT-ALL-TABLES-VIEW)」を参照してください。

ブロックおよびブロックされたクエリの詳細については、`pg_stat_activity`次の例のとおりにクエリを実行します。

```
SELECT
    blocked.pid,
    blocked.usename,
    blocked.query,
    blocking.pid AS blocking_id,
    blocking.query AS blocking_query,
    blocking.wait_event AS blocking_wait_event,
    blocking.wait_event_type AS blocking_wait_event_type
FROM pg_stat_activity AS blocked
JOIN pg_stat_activity AS blocking ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
where
blocked.wait_event = 'extend'
and blocked.wait_event_type = 'Lock';
 
   pid  | usename  |            query             | blocking_id |                         blocking_query                           | blocking_wait_event | blocking_wait_event_type
  ------+----------+------------------------------+-------------+------------------------------------------------------------------+---------------------+--------------------------
   7143 |  myuser  | insert into tab1 values (1); |        4600 | INSERT INTO tab1 (a) SELECT s FROM generate_series(1,1000000) s; | DataFileExtend      | IO
```

`Lock:extend`イベントの増加に寄与するリレーションを特定したら、次の方法を使用して競合を減らします。
+ パーティション化によって同じテーブルの競合を減らせるかどうかを調べます。挿入または更新されたタプルを異なるパーティショニングすると、競合を減らすことができます。パーティショニングについては、「[pg\$1partman エクステンションによる PostgreSQL パーティションの管理](PostgreSQL_Partitions.md)」を参照してください。
+ 待機イベントが主に更新アクティビティによるものである場合は、リレーションのフィルファクタ値を減らすことを検討してください。これにより、更新時に新しいブロックのリクエストを減らすことができます。フィルファクタとは、テーブルページをパッキングするための最大容量を決定する、テーブルの格納パラメータです。これは、ページの総容量に対するパーセンテージで表されます。フィルファクタパラメータの詳細については、PostgreSQL ドキュメントの「[CREATE TABLE](https://www.postgresql.org/docs/13/sql-createtable.html)」を参照してください。
**重要**  
この値を変更すると、ワークロードによってはパフォーマンスに悪影響を及ぼす可能性があるため、フィルファクタを変更する場合は、システムのテストを強くお勧めします。

### ネットワーク帯域幅の増加
<a name="wait-event.lockextend.actions.increase-network-bandwidth"></a>

書き込みレイテンシーが増加しているかどうかを確認するには、`WriteLatency`CloudWatch でメトリクスをチェックします。増加している場合は、Amazon CloudWatch の `WriteThroughput`、`ReadThroughput` メトリクスを使用し、DB インスタンスのストレージに関するトラフィックをモニタリングしてください。これらのメトリックは、ネットワーク帯域幅がワークロードのストレージアクティビティに十分かどうかを判断するのに役立ちます。

ネットワーク帯域幅が不足している場合は、増加してください。DB インスタンスがネットワーク帯域幅の制限に達している場合、帯域幅を増やす唯一の方法は DB インスタンスのサイズを大きくすることです。

CloudWatch のメトリクスの詳細については、「[Amazon RDS の Amazon CloudWatch インスタンスレベルのメトリクス](rds-metrics.md#rds-cw-metrics-instance)」を参照してください。DB インスタンスクラスごとの DB エンジンサポートについては、「[Amazon RDS の Amazon CloudWatch インスタンスレベルのメトリクス](rds-metrics.md#rds-cw-metrics-instance)」を参照してください。

# Lock:Relation
<a name="wait-event.lockrelation"></a>

`Lock:Relation`イベントは、別のトランザクションによって現在ロックされているテーブルまたはビュー (リレーション) のロックを取得するためにクエリが待っているときに発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.lockrelation.context.supported)
+ [

## Context
](#wait-event.lockrelation.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.lockrelation.causes)
+ [

## アクション
](#wait-event.lockrelation.actions)

## サポート対象エンジンバージョン
<a name="wait-event.lockrelation.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="wait-event.lockrelation.context"></a>

ほとんどの PostgreSQL コマンドは、テーブル内のデータへの同時アクセスを制御するために、暗黙のうちにロックを使用します。また、これらのロックは、アプリケーションコード内で`LOCK`コマンドによって明示的に使用することもできます。多くのロックモードは互いに互換性がないため、同じオブジェクトにアクセスしようとしているときにトランザクションをブロックすることがあります。このイベントが発生すると、RDS for PostgreSQL は `Lock:Relation` イベントを生成します。一般的な例をいくつか以下に示します。
+ `ACCESS EXCLUSIVE`のような排他的なロックは、すべての同時アクセスをブロックできます。`DROP TABLE`、`TRUNCATE`、`VACUUM FULL`、`CLUSTER`などのデータ定義言語 (DDL) オペレーションは、暗黙のうちに`ACCESS EXCLUSIVE`ロックを取得します。`ACCESS EXCLUSIVE` は、明示的にモードを指定しない `LOCK TABLE` ステートメントのデフォルトのロックモードでもあります。
+ テーブル上で`CREATE INDEX (without CONCURRENT)`を使用すると、`ROW EXCLUSIVE`ロックを取得するデータ操作言語 (DML) ステートメント`UPDATE`、`DELETE`、`INSERT`と競合します。

テーブルレベルのロックと競合するロックモードの詳細については、PostgreSQL ドキュメントの「[明示的なロック](https://www.postgresql.org/docs/13/explicit-locking.html)」を参照してください。

ブロックされたクエリとトランザクションは、通常、次のいずれかの方法でブロックを解除します。
+ クエリのブロック: アプリケーションがクエリをキャンセルするか、ユーザーがプロセスを終了できます。また、セッションのステートメントタイムアウトやデッドロック検出メカニズムによって、エンジンがクエリを強制終了させることもできます。
+ トランザクションのブロック: トランザクションが `ROLLBACK` または `COMMIT` を実行すると、トランザクションはブロックを停止します。ロールバックは、クライアントまたはネットワークの問題によってセッションが切断されたり、終了したときにも自動的に行われます。セッションは、データベースエンジンがシャットダウンされたり、システムがメモリ不足になったりしたときに終了できます。

## 待機時間が増加する原因の可能性
<a name="wait-event.lockrelation.causes"></a>

`Lock:Relation` イベントが通常よりも頻繁に発生する場合、パフォーマンスの問題を示している可能性があります。代表的な原因としては、以下が挙げられます。

**テーブルロックの競合による同時セッションの増加**  
競合するロックモードで同じテーブルをロックするクエリによる同時セッションの数が増加する可能性があります。

**メンテナンスオペレーション**  
`VACUUM`や`ANALYZE`のようなヘルスメンテナンスオペレーションは、競合するロックの数を大幅に増加させる可能性があります。`VACUUM FULL`は`ACCESS EXCLUSIVE`のロックを、`ANALYSE`は`SHARE UPDATE EXCLUSIVE`のロックを取得します。どちらのタイプのロックも、`Lock:Relation`待機イベントを引き起こすことがあります。また、マテリアライズドビューのリフレッシュなどのアプリケーションデータのメンテナンスオペレーションも、ブロックされたクエリとトランザクションを増加することもあります。

**リーダーインスタンスをロックする**  
ライターとリーダーが保持しているリレーションロックの間に矛盾がある可能性があります。現在は、`ACCESS EXCLUSIVE` リレーションロックのみが、リーダーインスタンスにレプリケートされます。ただし、`ACCESS EXCLUSIVE` リレーションロックは、リーダーが保持する `ACCESS SHARE` リレーションロックと競合します。これにより、リーダーのロックリレーション待機イベントが増加する可能性があります。

## アクション
<a name="wait-event.lockrelation.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。

**Topics**
+ [

### SQL ステートメントのブロックによる影響を軽減
](#wait-event.lockrelation.actions.reduce-blocks)
+ [

### メンテナンスオペレーションの影響を最小限に抑える
](#wait-event.lockrelation.actions.maintenance)

### SQL ステートメントのブロックによる影響を軽減
<a name="wait-event.lockrelation.actions.reduce-blocks"></a>

SQL ステートメントのブロックによる影響を軽減するには、可能なところではアプリケーションコードを修正します。ブロックを減らすための 2 つの一般的な方法は以下のとおりです。
+ `NOWAIT` オプションを使用する: `SELECT` や `LOCK` ステートメントなど、一部の SQL コマンドはこのオプションをサポートしています。`NOWAIT`指示文は、ロックをすぐに取得できない場合、ロックへのクエリをキャンセルします。この方法は、ブロックされたセッションが、その後ろにあるブロックされたセッションが積み重なるのを防ぐのに役立ちます。

  例えば、トランザクション A がトランザクション B に保持されているロックを待っているとします。ここで、B がトランザクション C によってロックされているテーブルのロックをリクエストすると、トランザクション C が完了するまでトランザクション A がブロックされる可能性があります。ただし、トランザクション B が C のロックを要求するときに`NOWAIT`を使用する場合、トランザクションBは迅速に失敗し、トランザクション A が無期限に待機する必要がないことを保証できます。
+ `SET lock_timeout` を使用する: `lock_timeout` 値を設定して、SQL ステートメントがリレーションでロックを取得するのを待機する時間を制限します。指定されたタイムアウト時間内にロックが取得されなかった場合、ロックを要求したトランザクションはキャンセルされます。この値はセッションレベルで設定します。

### メンテナンスオペレーションの影響を最小限に抑える
<a name="wait-event.lockrelation.actions.maintenance"></a>

`VACUUM`や`ANALYZE`のようなメンテナンスオペレーションは重要です。これらのメンテナンス作業に関連する`Lock:Relation`待機イベントを見つけても、それらをオフにしないことをお勧めします。次のようなアプローチにより、これらの操作の影響を最小限に抑えることができます。
+ オフピーク時にメンテナンス操作をマニュアルで実行します。
+ オートバキュームタスクによる`Lock:Relation`待機をへらすには、必要なオートバキュームチューニングを実行します。オートバキュームのチューニングについては、*Amazon RDS ユーザーガイド*の「[Amazon RDS での PostgreSQL オートバキュームの使用](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html)」を参照してください。

# Lock:transactionid
<a name="wait-event.locktransactionid"></a>

`Lock:transactionid`イベントは、トランザクションが行レベルのロックを待っているときに発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.locktransactionid.context.supported)
+ [

## Context
](#wait-event.locktransactionid.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.locktransactionid.causes)
+ [

## アクション
](#wait-event.locktransactionid.actions)

## サポート対象エンジンバージョン
<a name="wait-event.locktransactionid.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="wait-event.locktransactionid.context"></a>

イベント`Lock:transactionid`は、トランザクションが、同時に実行されているトランザクションにすでに付与された行レベルのロックを取得しようとすると発生します。を示すセッションは、`Lock:transactionid`待機イベントがこのロックのためにブロックされていることを示します。`COMMIT`または`ROLLBACK`ステートメントでブロックされているトランザクションの完了後、ブロックされたトランザクションを続行できます。

RDS for PostgreSQL のマルチバージョン同時実行制御セマンティクスは、リーダーがライターを、ライターがリーダーをブロックしないことを保証します。行レベルの競合が発生するには、ブロックおよびブロックされたトランザクションで、次のタイプの競合するステートメントを発行する必要があります。
+ `UPDATE`
+ `SELECT … FOR UPDATE`
+ `SELECT … FOR KEY SHARE`

ステートメント`SELECT … FOR KEY SHARE`は特殊なケースです。データベースは、レファレンスの整合性のパフォーマンスを最適化するために、`FOR KEY SHARE`節を使用します。行に対する行レベルロックは、行を参照している他のテーブルの`INSERT`、`UPDATE`、`DELETE`コマンドをブロックできます。

## 待機時間が増加する原因の可能性
<a name="wait-event.locktransactionid.causes"></a>

このイベントが通常よりも頻繁に発生する場合、通常は`UPDATE`、`SELECT … FOR UPDATE`、または`SELECT … FOR KEY SHARE`ステートメントが以下の条件と組み合わさることが原因です。

**Topics**
+ [

### 同時実行数が多い
](#wait-event.locktransactionid.concurrency)
+ [

### トランザクションでのアイドル状態
](#wait-event.locktransactionid.idle)
+ [

### トランザクションの実行時間が長い
](#wait-event.locktransactionid.long-running)

### 同時実行数が多い
<a name="wait-event.locktransactionid.concurrency"></a>

RDS for PostgreSQL は、きめ細かい行レベルのロックセマンティクスを使用できます。以下の条件が満たされると、行レベルの同時実行が発生する可能性が高くなります。
+ 同時性の高いワークロードは、同じ行で同時実行します。
+ 同時実行数が増加します。

### トランザクションでのアイドル状態
<a name="wait-event.locktransactionid.idle"></a>

時々、`pg_stat_activity.state`列には`idle in transaction`値が表示されます。この値は、トランザクションをスタートしていても、まだ`COMMIT`または`ROLLBACK`を発行していないセッションに表示されます。`pg_stat_activity.state`値が`active`ではない場合、`pg_stat_activity`に表示されるクエリは、実行を終了した最新のクエリになります。ブロックされているセッションは、開いているトランザクションがロックを保持しているため、クエリを積極的に処理しません。

アイドル状態のトランザクションが行レベルロックを取得した場合は、他のセッションがそのロックを取得するのを妨害する可能性があります。この状態は、待機イベント`Lock:transactionid`の頻発につながります。問題を診断するには、`pg_stat_activity`そして`pg_locks`からの出力を検証します。

### トランザクションの実行時間が長い
<a name="wait-event.locktransactionid.long-running"></a>

実行時間が長いトランザクションは、長時間ロックされます。これらの長時間のロックは、他のトランザクションの実行をブロックすることがあります。

## アクション
<a name="wait-event.locktransactionid.actions"></a>

行ロックは`UPDATE`、`SELECT … FOR UPDATE`、または`SELECT … FOR KEY SHARE`ステートメント間の競合です。解決策を試す前に、これらのステートメントが同じ行で実行されているかどうかを調べます。この情報をもとに、次のセクションで説明する戦略を選択してください。

**Topics**
+ [

### 同時実行数の多さに対応
](#wait-event.locktransactionid.actions.problem)
+ [

### アイドル状態のトランザクションに対応する
](#wait-event.locktransactionid.actions.find-blocker)
+ [

### 長時間実行されるトランザクションへの対応
](#wait-event.locktransactionid.actions.concurrency)

### 同時実行数の多さに対応
<a name="wait-event.locktransactionid.actions.problem"></a>

同時実行数が問題になる場合は、以下から 1 つの方法を試行します。
+ アプリケーションの同時実行数を減らします。例えば、アクティブなセッションの数を減らします。
+ 接続プールを実装します。RDS プロキシを使用して接続をプールする方法については、「[Amazon RDS Proxy ](rds-proxy.md)」を参照してください。
+ アプリケーションまたはデータモデルを設計し、`UPDATE`および`SELECT … FOR UPDATE`ステートメントの競合を避けてください。また、`SELECT … FOR KEY SHARE`ステートメントにアクセスされる外部キーの数を減らすこともできます。

### アイドル状態のトランザクションに対応する
<a name="wait-event.locktransactionid.actions.find-blocker"></a>

`pg_stat_activity.state`が`idle in transaction`を示している場合は、以下の方法を使用します。
+ 可能な限り、オートコミットをオンにします。この方法では、`COMMIT`または`ROLLBACK`を待っている間に、トランザクションが他のトランザクションをブロックすることを防ぎます。
+ `COMMIT`、`ROLLBACK`、または`END`が不足しているコードパスを検索します。
+ アプリケーションの例外処理ロジックに、常に有効な`end of transaction`へのパスが設定されていることを確認してください。
+ `COMMIT`または`ROLLBACK`でトランザクションを完了した後、アプリケーションがクエリの結果を処理することを確認します。

### 長時間実行されるトランザクションへの対応
<a name="wait-event.locktransactionid.actions.concurrency"></a>

長時間実行されるトランザクションが`Lock:transactionid`の発生を頻繁に引き起こす場合、以下の方法を試します。
+ 長時間実行されるトランザクションが行をロックしないようにします。
+ 可能であれば、オートコミットを実装してクエリの長さを制限します。

# Lock:tuple
<a name="wait-event.locktuple"></a>

`Lock:tuple` イベントは、バックエンドプロセスがタプルのロックを取得するのを待っているときに発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.locktuple.context.supported)
+ [

## Context
](#wait-event.locktuple.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.locktuple.causes)
+ [

## アクション
](#wait-event.locktuple.actions)

## サポート対象エンジンバージョン
<a name="wait-event.locktuple.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="wait-event.locktuple.context"></a>

イベント`Lock:tuple`は、バックエンドがタプルのロック取得を待っている間、別のバックエンドが同じタプルで競合するロックを保持していることを示します。次の表では、セッションが`Lock:tuple`イベントを生成するシナリオを示します。


|  時間  |  セッション 1  |  セッション 2  |  セッション 3  | 
| --- | --- | --- | --- | 
|  t1  |  トランザクションをスタートします。  |    |    | 
|  t2  |  行 1 を更新します。  |    |    | 
|  t3  |    |  行 1 を更新します。セッションは、タプルの排他ロックを取得してから、セッション1がコミットまたはロールバックによってロックを解放するのを待機します。  |    | 
|  t4  |    |    |  行 1 を更新します。セッションは、セッション 2 がタプルの排他ロックを解放するのを待機します。  | 

または、ベンチマークツール`pgbench`を使用してこの待機イベントをシミュレートすることができます。多数の同時セッションを構成して、カスタムSQLファイルでテーブル内の同じ行を更新します。

競合するロックモードの詳細については、「PostgreSQL のドキュメント」の「[明示的なロック](https://www.postgresql.org/docs/current/explicit-locking.html)」を参照してください。`pgbench`の詳細については、「PostgreSQL のドキュメント」の「[pgbench](https://www.postgresql.org/docs/current/pgbench.html)」を参照してください。

## 待機時間が増加する原因の可能性
<a name="wait-event.locktuple.causes"></a>

このイベントが通常よりも頻繁に表示される場合、パフォーマンスの問題を示している可能性があり、典型的な原因は次のとおりです。
+ `UPDATE`または`DELETE`ステートメントの実行により、同じタプルへの競合するロックを取得しようとしている同時セッションが多数あります。
+ 同時実行数の多いセッションでは、`FOR UPDATE`または`FOR NO KEY UPDATE`ロックモードを使用して`SELECT`ステートメントを実行します。
+ さまざまな要因により、アプリケーションまたは接続プールが同じオペレーションを実行するため、より多くのセッションを開きます。新しいセッションが同じ行を変更しようとすると、DB ロードのスパイクが発生して`Lock:tuple`が表示されることがあります。

詳細については、「PostgreSQL のドキュメント」の「[行レベルのロック](https://www.postgresql.org/docs/current/explicit-locking.html#LOCKING-ROWS)」を参照してください。

## アクション
<a name="wait-event.locktuple.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。

**Topics**
+ [

### アプリケーションロジックを調査する
](#wait-event.locktuple.actions.problem)
+ [

### ブロッカーセッションを見つける
](#wait-event.locktuple.actions.find-blocker)
+ [

### 同時実行数が多いときにそれを減らす
](#wait-event.locktuple.actions.concurrency)
+ [

### ボトルネックのトラブルシューティング
](#wait-event.locktuple.actions.bottlenecks)

### アプリケーションロジックを調査する
<a name="wait-event.locktuple.actions.problem"></a>

ブロッカーセッションが長い間`idle in transaction`ステートメントにあったかどうかを確認します。その場合は、短期的な解決策としてブロッカーセッションの終了を検討してください。`pg_terminate_backend` 関数を使用することもできます。この関数の詳細については、「PostgreSQL のドキュメント」の「[サーバーシグナリング関数](https://www.postgresql.org/docs/13/functions-admin.html#FUNCTIONS-ADMIN-SIGNAL)」を参照してください。

長期的な解決策としては、以下を実行してください。
+ アプリケーションロジックを調整します。
+ `idle_in_transaction_session_timeout` パラメータを使用します。このパラメータは、指定された時間より長くアイドル状態であったオープントランザクションを持つセッションを終了させます。詳細については、PostgreSQL ドキュメントの 「[Client Connection Defaults (クライアント接続のデフォルト)](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT)」 を参照してください。
+ 可能な限りオートコミットを使用します。詳細については、PostgreSQL ドキュメントの 「[Client authentication (クライアント認証)](https://www.postgresql.org/docs/current/ecpg-sql-set-autocommit.html)」 を参照してください。

### ブロッカーセッションを見つける
<a name="wait-event.locktuple.actions.find-blocker"></a>

`Lock:tuple`の待機イベントが発生している間に、どのロックが互いに依存しているかを探して、ブロッカーとブロックされたセッションを特定します。詳細については、PostgreSQL wiki にの「[依存関係情報のロック](https://wiki.postgresql.org/wiki/Lock_dependency_information)」を参照してください。

次の例では、`tuple`でフィルタリングして`wait_time`で順序付けし、すべてのセッションへのクエリを実行しています。

```
SELECT blocked_locks.pid AS blocked_pid,
         blocking_locks.pid AS blocking_pid,
         blocked_activity.usename AS blocked_user,
         blocking_activity.usename AS blocking_user,
         now() - blocked_activity.xact_start AS blocked_transaction_duration,
         now() - blocking_activity.xact_start AS blocking_transaction_duration,
         concat(blocked_activity.wait_event_type,':',blocked_activity.wait_event) AS blocked_wait_event,
         concat(blocking_activity.wait_event_type,':',blocking_activity.wait_event) AS blocking_wait_event,
         blocked_activity.state AS blocked_state,
         blocking_activity.state AS blocking_state,
         blocked_locks.locktype AS blocked_locktype,
         blocking_locks.locktype AS blocking_locktype,
         blocked_activity.query AS blocked_statement,
         blocking_activity.query AS blocking_statement
    FROM pg_catalog.pg_locks blocked_locks
    JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid
    JOIN pg_catalog.pg_locks blocking_locks
        ON blocking_locks.locktype = blocked_locks.locktype
        AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE
        AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation
        AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page
        AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple
        AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid
        AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid
        AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid
        AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid
        AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid
        AND blocking_locks.pid != blocked_locks.pid
    JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid
    WHERE NOT blocked_locks.GRANTED;
```

### 同時実行数が多いときにそれを減らす
<a name="wait-event.locktuple.actions.concurrency"></a>

`Lock:tuple`イベントは、特にワークロードの多い時間帯に、コンスタントに発生する可能性があります。このような状況では、非常にビジーな行への同時実行数を減らすことを検討してください。多くの場合、キューまたはブールロジックを制御する行の数行だけで、これらの行は非常にビジーになります。

ビジネス要件、アプリケーションロジック、およびワークロードタイプに応じて、さまざまなアプローチを使用することで、競合を減らすことができます。例えば、次のオペレーションを実行できます。
+ テーブルとデータロジックを再設計し、競合を減らします。
+ アプリケーションロジックを変更して、行レベルで高い競合を減らします。
+ 行レベルのロックを活用してクエリを再設計します。
+ `NOWAIT`節はリトライオペレーションで使用します。
+ 楽観的かつハイブリッドロックロジックの同時実行制御の使用を検討します。
+ データベースの隔離レベルの変更を検討してください。

### ボトルネックのトラブルシューティング
<a name="wait-event.locktuple.actions.bottlenecks"></a>

`Lock:tuple`は、CPU の枯渇や Amazon EBS 帯域幅の最大使用率などのボトルネックを発生させることがあります。ボトルネックを減らすには、次のアプローチを検討します。
+ インスタンスクラスタイプをスケールアップします。
+ リソースを大量に消費するクエリを最適化します。
+ アプリケーションロジックを変更します。
+ ほとんどアクセスされないデータをアーカイブします。

# LWLock:BufferMapping (LWLock:buffer\$1mapping)
<a name="wait-event.lwl-buffer-mapping"></a>

このイベントは、セッションがデータブロックを共有バッファプール内のバッファに関連付けるのを待っているときに発生します。

**注記**  
RDS for PostgreSQL のバージョン 13 以降では、このイベントの名前は `LWLock:BufferMapping` になります。RDS for PostgreSQL のバージョン 12 以前では、このイベントの名前は `LWLock:buffer_mapping` になります。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.lwl-buffer-mapping.context.supported)
+ [

## Context
](#wait-event.lwl-buffer-mapping.context)
+ [

## 原因
](#wait-event.lwl-buffer-mapping.causes)
+ [

## アクション
](#wait-event.lwl-buffer-mapping.actions)

## サポート対象エンジンバージョン
<a name="wait-event.lwl-buffer-mapping.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL バージョン 9.6 以降に関連します。

## Context
<a name="wait-event.lwl-buffer-mapping.context"></a>

*共有バッファプール*は、プロセスで使用されている、または使用されていたすべてのページを保持する PostgreSQL のメモリ領域です。プロセスがページを必要とするとき、そのページを共有バッファプールに読み取ります。`shared_buffers`パラメータは、共有バッファサイズを設定し、テーブルとインデックスページを格納するためのメモリ領域を予約します。このパラメータを変更する場合は、必ずデータベースを再起動してください。

`LWLock:buffer_mapping`待機イベントは、以下の場合に発生します。
+ プロセスは、バッファテーブルでページを検索し、共有バッファマッピングロックを取得します。
+ プロセスは、ページをバッファプールにロードし、排他的バッファマッピングロックを取得します。
+ プロセスは、プールからページを削除し、排他バッファマッピングロックを取得します。

## 原因
<a name="wait-event.lwl-buffer-mapping.causes"></a>

このイベントが通常よりも頻繁に発生する場合、パフォーマンスの問題を示していることがあり、データベースは共有バッファプールにページインとアウトページングを行っています。代表的な原因としては、以下が挙げられます。
+ 大きなクエリ
+ 肥大化したインデックスとテーブル
+ フルテーブルスキャン
+ ワーキングセットより小さい共有プールサイズ

## アクション
<a name="wait-event.lwl-buffer-mapping.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。

**Topics**
+ [

### バッファ関連のメトリクスをモニタリングする
](#wait-event.lwl-buffer-mapping.actions.monitor-metrics)
+ [

### インデックス作成戦略を評価する
](#wait-event.lwl-buffer-mapping.actions.indexes)
+ [

### 迅速に確保しなければならないバッファの数を減らす
](#wait-event.lwl-buffer-mapping.actions.buffers)

### バッファ関連のメトリクスをモニタリングする
<a name="wait-event.lwl-buffer-mapping.actions.monitor-metrics"></a>

`LWLock:buffer_mapping`がスパイクを待機したら、バッファヒット率を調べます。これらのメトリクスを使用すると、バッファキャッシュで何が起こっているかをより深く理解できます。次のメトリックを検証します。

`blks_hit`  
この Performance Insights カウンターメトリクスは、共有バッファプールから取得されたブロックの数を示します。`LWLock:buffer_mapping`の待機イベントが表示された後、`blks_hit`のスパイクを観察することがあります。

`blks_read`  
この Performance Insights カウンターメトリクスは、共有バッファプールへの読み取りのため、 I/O を必要とするブロックの数を示します。`LWLock:buffer_mapping`待機イベントまでに`blks_read`のスパイクが観察されることがあります。

### インデックス作成戦略を評価する
<a name="wait-event.lwl-buffer-mapping.actions.indexes"></a>

インデックス作成戦略がパフォーマンスが低下させていないことを確認するには、次を確認してください。

インデックスの肥大化  
インデックスとテーブルの肥大化によって、不要なページが共有バッファに読み込まれないようにします。テーブルに未使用の行がある場合は、データをアーカイブし、テーブルから行を削除することを検討してください。その後、サイズ変更されたテーブルのインデックスを再構築できます。

頻繁に使用するクエリのインデックス  
最適なインデックスがあるかどうかを判断するには、Performance Insights で DB エンジンのメトリクスをモニタリングします。`tup_returned`メトリクスは、読み込まれた行数を示します。`tup_fetched`メトリクスは、クライアントに返される行数を示します。`tup_returned`が`tup_fetched`を大幅に超える場合、データが適切にインデックスされていない可能性があります。また、テーブルの統計が最新ではない可能性があります。

### 迅速に確保しなければならないバッファの数を減らす
<a name="wait-event.lwl-buffer-mapping.actions.buffers"></a>

`LWLock:buffer_mapping`待機イベントを減らすには、迅速に割り当てる必要があるバッファの数を減らしてください。1 つの戦略として、より小規模なバッチオペレーションを実行します。テーブルをパーティション化することで、より小さなバッチを実現できることがあります。

# LWLock:BufferIO (IPC:BufferIO)
<a name="wait-event.lwlockbufferio"></a>

`LWLock:BufferIO` イベントは、RDS for PostgreSQL が同時にページにアクセスしようとしているときに、他のプロセスが入出力 (I/O) オペレーションの完了を待っているときに発生します。その目的は、同じページを共有バッファに読み込むことです。

**Topics**
+ [

## 関連するエンジンのバージョン
](#wait-event.lwlockbufferio.context.supported)
+ [

## Context
](#wait-event.lwlockbufferio.context)
+ [

## 原因
](#wait-event.lwlockbufferio.causes)
+ [

## アクション
](#wait-event.lwlockbufferio.actions)

## 関連するエンジンのバージョン
<a name="wait-event.lwlockbufferio.context.supported"></a>

この待機イベント情報は、すべての RDS for PostgreSQL のバージョンに関連しています。RDS for PostgreSQL 12 以前のバージョンでは、この待機イベントは lwlock:buffer\$1io という名前でしたが、RDS for PostgreSQL 13 バージョンでは lwlock:bufferio という名前です。RDS for PostgreSQL 14 バージョンから、BufferIO 待機イベントは `LWLock` から `IPC` 待機イベントタイプ (IPC:BufferIO) に移動されました。

## Context
<a name="wait-event.lwlockbufferio.context"></a>

各共有バッファは、ブロック (またはページ) が共有バッファプールの外部で取得される必要があるたびに、`LWLock:BufferIO`待機イベントに関連付けられた I/O ロックを持ちます。

このロックは、すべての同じブロックへのアクセスを必要とする複数のセッションを処理するために使用されます。このブロックは、`shared_buffers`パラメータで定義された共有バッファプールの外部から読み取る必要があります。

共有バッファプール内でページが読み込まれると、`LWLock:BufferIO`ロックが解除されます。

**注記**  
`LWLock:BufferIO`待機イベントは[IO:DataFileRead](wait-event.iodatafileread.md)待機イベントに先行します。`IO:DataFileRead`待機イベントは、データがストレージから読み込まれている間に発生します。

ライトウェイトロックの詳細については、「[ロックの概要](https://github.com/postgres/postgres/blob/65dc30ced64cd17f3800ff1b73ab1d358e92efd8/src/backend/storage/lmgr/README#L20)」を参照してください。

## 原因
<a name="wait-event.lwlockbufferio.causes"></a>

`LWLock:BufferIO`上位待機中に表示されるイベントの一般的な原因には、次のものがあります。
+ 複数のバックエンドまたは接続が I/O オペレーションを保留している同じページにアクセスしようとしている
+ 共有バッファプール (`shared_buffers`パラメータで定義) のサイズと、現在のワークロードが必要とするバッファ数の比率
+ 共有バッファプールのサイズが、他の操作によって削除されるページ数とのバランスが悪い
+ エンジンが共有バッファプールに必要以上のページを読み込む必要がある大規模なインデックスまたは肥大化したインデックス
+ DB エンジンが強制的に必要以上に多くのページをテーブルから読み取るインデックスの欠落
+ チェックポイント発生が頻繁すぎたり、変更されたページをフラッシュする必要が多すぎる
+ 同じページで操作を実行しようとするデータベース接続が突然スパイクする

## アクション
<a name="wait-event.lwlockbufferio.actions"></a>

待機イベントの原因に応じたさまざまなアクションを実行することをお勧めします。
+ `BufferCacheHitRatio`の急減と`LWLock:BufferIO`待機イベントの相関関係のため、Amazon CloudWatch メトリクスを観察します。この効果は、共有バッファの設定が小さいことを意味することがあります。増やすか、DB インスタンスクラスをスケールアップする必要がある場合があります。ワークロードをより多くのリーダーノードに分割できます。
+ `LWLock:BufferIO`が`BufferCacheHitRatio`のメトリックと一致する場合は、ワークロードのピーク時間に基づいて`max_wal_size`と`checkpoint_timeout`をチューニングしてください。次に、原因となっているクエリを特定します。
+ 未使用のインデックスがあるかどうかを確認し、それらを削除します。
+ パーティション化されたテーブルを使用します (パーティション化されたインデックスもあります)。これにより、インデックスの並べ替えを低く抑え、その影響を軽減することができます。
+ 不必要に列のインデックスを作成しないようにします。
+ 接続プールを使用して、突然のデータベース接続スパイクを防ぎます。
+ ベストプラクティスとして、データベースへの最大接続数を制限します。

# LWLock:buffer\$1content (BufferContent)
<a name="wait-event.lwlockbuffercontent"></a>

この`LWLock:buffer_content`待機イベントは、セッションがデータページをメモリに読み取るまたは書き込むために待機中、他のセッションがそのページを書き込み用にロックしている場合に発生します。RDS for PostgreSQL 13 以降では、この待機イベントは `BufferContent` と呼ばれます。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.lwlockbuffercontent.context.supported)
+ [

## Context
](#wait-event.lwlockbuffercontent.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.lwlockbuffercontent.causes)
+ [

## アクション
](#wait-event.lwlockbuffercontent.actions)

## サポート対象エンジンバージョン
<a name="wait-event.lwlockbuffercontent.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="wait-event.lwlockbuffercontent.context"></a>

データの読み取りや操作のために、PostgreSQL は共有メモリバッファを介してデータにアクセスします。バッファから読み取るために、プロセスは共有モードでバッファコンテンツに対する軽量ロック (LwLock) を取得します。バッファに書き込むには、排他モードでそのロックを取得します。共有ロックを使用すると、他のプロセスがそのコンテンツの共有ロックを同時に取得できます。排他ロックは、他のプロセスによるいかなるタイプのロック取得も防ぎます。

`LWLock:buffer_content`(`BufferContent`) イベントは、複数のプロセスが特定のバッファの内容をロックしようとしていることを示します。

## 待機時間が増加する原因の可能性
<a name="wait-event.lwlockbuffercontent.causes"></a>

`LWLock:buffer_content` (`BufferContent`) イベントが通常より頻繁に発生し、パフォーマンスの問題を示している可能性がある場合、代表的な原因として以下が挙げられます。

**同一データに対する同時更新の増加**  
同じバッファコンテンツを更新するクエリによる同時実行セッションの数が増加する可能性があります。この競合は、インデックスの多いテーブルではより顕著になることがあります。

**ワークロードデータがメモリ内に存在しない**  
アクティブなワークロードが処理しているデータがメモリ上にない場合、これらの待機イベントが増加する可能性があります。この効果は、ロックを保持しているプロセスが、ディスク I/O 操作の実行中にロックを長く維持できるためです。

**外部キー制約の過度の使用**  
外部キー制約により、プロセスがバッファコンテンツロックを保持する時間を増やすことがあります。この効果は、読み取り操作では、そのキーが更新されている間、参照キーに対する共有バッファコンテンツのロックが必要になるためです。

## アクション
<a name="wait-event.lwlockbuffercontent.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。`LWLock:buffer_content`(`BufferContent`)イベントは、Amazon RDS Performance Insights を使用するか、ビュー`pg_stat_activity`のクエリで特定することができます。

**Topics**
+ [

### インメモリ効率の向上
](#wait-event.lwlockbuffercontent.actions.in-memory)
+ [

### 外部キー制約の使用を減らす
](#wait-event.lwlockbuffercontent.actions.foreignkey)
+ [

### 未使用インデックスの削除
](#wait-event.lwlockbuffercontent.actions.indexes)
+ [

### シーケンスを使用する場合は、キャッシュサイズを増やしてください
](#wait-event.lwlockbuffercontent.actions.sequences)

### インメモリ効率の向上
<a name="wait-event.lwlockbuffercontent.actions.in-memory"></a>

アクティブなワークロードデータがメモリ内に存在する可能性を高めるには、テーブルをパーティション化するか、インスタンスクラスをスケールアップします。DB インスタンスクラスの詳細については、「[ DB インスタンスクラス](Concepts.DBInstanceClass.md)」を参照してください。

### 外部キー制約の使用を減らす
<a name="wait-event.lwlockbuffercontent.actions.foreignkey"></a>

外部キー制約の使用で、`LWLock:buffer_content`(`BufferContent`)待機イベントが多発しているワークロードを調査します。不要な外部キーの制約を削除します。

### 未使用インデックスの削除
<a name="wait-event.lwlockbuffercontent.actions.indexes"></a>

`LWLock:buffer_content` (`BufferContent`) 待機イベントが多いワークロードで、未使用のインデックスを特定して削除します。

### シーケンスを使用する場合は、キャッシュサイズを増やしてください
<a name="wait-event.lwlockbuffercontent.actions.sequences"></a>

テーブルがシーケンスを使用している場合は、キャッシュサイズを増やして、シーケンスページとインデックスページの競合をなくします。各シーケンスは共有メモリ内の 1 ページです。定義済みのキャッシュは接続ごとです。多くの同時セッションによってシーケンス値を取得している場合、これではワークロードを処理するのに不十分な場合があります。

# LWLock:lock\$1manager (LWLock:lockmanager)
<a name="wait-event.lw-lock-manager"></a>

このイベントは、RDS for PostgreSQL エンジンが、高速パスロックが不可能な場合に共有ロックのメモリ領域を維持し、ロックの割り当て、チェック、および解放を行うときに発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.lw-lock-manager.context.supported)
+ [

## Context
](#wait-event.lw-lock-manager.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.lw-lock-manager.causes)
+ [

## アクション
](#wait-event.lw-lock-manager.actions)

## サポート対象エンジンバージョン
<a name="wait-event.lw-lock-manager.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL バージョン 9.6 以降に関連します。RDS for PostgreSQL のバージョン 13 より前のリリースでは、この待機イベントの名前は `LWLock:lock_manager` になります。RDS for PostgreSQL のバージョン 13 以降のリリースでは、この待機イベントの名前は `LWLock:lockmanager` になります。

## Context
<a name="wait-event.lw-lock-manager.context"></a>

SQL ステートメントを発行すると、RDS for PostgreSQL は同時オペレーション中にデータベースの構造、データ、および整合性を保護するためにロックを記録します。エンジンは、高速パスロックまたは高速ではないパスロックを使用して、この目標を達成できます。高速ではないパスロックは、高速パスロックよりも高価で、オーバーヘッドも多く発生します。

### 高速パスロック
<a name="wait-event.lw-lock-manager.context.fast-path"></a>

バックエンドプロセスでは、頻繁にロックされロック解除されるがめったに競合しないロックのオーバーヘッドを減らすために、高速パスロックを使用できます。データベースでは、以下の基準を満たすロックにこのメカニズムを使用します。
+ DEFAULT ロック方式を使用します。
+ これらは、共有関係ではなく、データベースリレーションに対するロックを表します。
+ これらは競合する可能性が低い弱いロックです。
+ エンジンは、競合するロックが存在する可能性がないことをすばやく確認できます。

エンジンは、以下のいずれかの条件が true の場合、高速パスロックを使用できません。
+ ロックが上記の条件を満たしていません。
+ バックエンドプロセスに使用できるスロットはこれ以上ありません。

高速パスロック用にクエリを調整するには、次のクエリを使用できます。

```
SELECT count(*), pid, mode, fastpath
  FROM pg_locks
 WHERE fastpath IS NOT NULL
 GROUP BY 4,3,2
 ORDER BY pid, mode;
 count | pid  |      mode       | fastpath
-------+------+-----------------+----------
16 | 9185 | AccessShareLock | t
336 | 9185 | AccessShareLock | f
1 | 9185 | ExclusiveLock   | t
```

次のクエリでは、データベース全体の合計のみを表示します。

```
SELECT count(*), mode, fastpath
  FROM pg_locks
 WHERE fastpath IS NOT NULL
 GROUP BY 3,2
 ORDER BY mode,1;
count |      mode       | fastpath
-------+-----------------+----------
16 | AccessShareLock | t
337 | AccessShareLock | f
1 | ExclusiveLock   | t
(3 rows)
```

高速パスロックの詳細については、「PostgreSQL ロックマネージャ README」 の[fast path](https://github.com/postgres/postgres/blob/master/src/backend/storage/lmgr/README#L70-L76)および「PostgreSQL ドキュメント」の[pg-locks](https://www.postgresql.org/docs/9.3/view-pg-locks.html#AEN98195)を参照してください。

### ロックマネージャのスケーリング問題の例
<a name="wait-event.lw-lock-manager.context.lock-manager"></a>

この例では、`purchases`という名前のテーブルが 5 年分のデータを日ごとにパーティション化して保存しています。各パーティションには 2 つのインデックスがあります。次の一連のイベントが発生します。

1. 何日分ものデータをクエリすると、データベースは多くのパーティションを読み取る必要があります。

1. データベースは、各パーティションに対してロックエントリを作成します。パーティションインデックスがオプティマイザアクセスパスの一部である場合、データベースはそれらのロックエントリも作成します。

1. 同じバックエンドプロセスでリクエストされたロックエントリの数が`FP_LOCK_SLOTS_PER_BACKEND`の値である16より大きい場合、ロックマネージャは非高速パスロック方式を使用します。

最新のアプリケーションには何百ものセッションがあることがあります。同時セッションが適切なパーティションプルーニングを行わずに親を照会している場合、データベースは数百または数千の非高速パスロックを作成することがあります。通常、この同時実行が vCPUs の数よりも多いと、`LWLock:lock_manager`待機イベントが表示されます。

**注記**  
`LWLock:lock_manager`待機イベントは、データベーススキーマのパーティションまたはインデックスの数とは関係ありません。代わりに、データベースが制御する必要がある非高速パスロックの数と関係しています。

## 待機時間が増加する原因の可能性
<a name="wait-event.lw-lock-manager.causes"></a>

`LWLock:lock_manager`待機イベントが通常より頻繁に発生する場合は、おそらくパフォーマンスの問題を示しており、突然のスパイクが発生する原因として最も可能性が高いものは次のとおりです。
+ 同時アクティブセッションは、高速パスロックを使用しないクエリを実行しています。また、これらのセッション数が最大 vCPU を超えています。
+ 多数の同時アクティブセッションが、大きくパーティション化されたテーブルにアクセスしています。各パーティションには複数のインデックスがあります。
+ データベースで接続ストームが発生しています。デフォルトでは、一部のアプリケーションと接続プールソフトウェアは、データベースが遅い場合により多くの接続を作成します。これは問題を悪化させます。接続ストームが発生しないように接続プールソフトウェアをチューニングします。
+ 多数のセッションが、パーティションをプルーニングせずに親テーブルをクエリします。
+ データ定義言語 (DDL)、データ操作言語 (DML)、またはメンテナンスコマンドは、頻繁にアクセスまたは変更されるビジーリレーションあるいはタプルのいずれかを排他的にロックします。

## アクション
<a name="wait-event.lw-lock-manager.actions"></a>

`CPU`待機イベントが発生する場合、必ずしもパフォーマンスの問題を示しているとは限りません。パフォーマンスが低下し、この待機イベントが DB ロードを支配している場合にのみ、このイベントに応答します。

**Topics**
+ [

### パーティションプルーニングを使用する
](#wait-event.lw-lock-manager.actions.pruning)
+ [

### 不要なインデックスを削除する
](#wait-event.lw-lock-manager.actions.indexes)
+ [

### 高速パスロック用にクエリをチューニングする
](#wait-event.lw-lock-manager.actions.tuning)
+ [

### 他の待機イベントに合わせてチューニングする
](#wait-event.lw-lock-manager.actions.other-waits)
+ [

### ハードウェアのボトルネックを減らす
](#wait-event.lw-lock-manager.actions.hw-bottlenecks)
+ [

### 接続プーラーを使用する
](#wait-event.lw-lock-manager.actions.pooler)
+ [

### RDS for PostgreSQL バージョンのアップグレード
](#wait-event.lw-lock-manager.actions.pg-version)

### パーティションプルーニングを使用する
<a name="wait-event.lw-lock-manager.actions.pruning"></a>

*パーティションプルーニング*とは、宣言によってパーティション分割されたテーブルに対するクエリ最適化戦略のことで、不要なパーティションをテーブルスキャンから除外し、パフォーマンスを向上させます。パーティションプルーニングは、デフォルトで有効になっています。オフになっている場合は、次のようにオンにします。

```
SET enable_partition_pruning = on;
```

クエリの`WHERE`節にパーティショニングに使用される列が含まれる場合は、パーティションのプルーニングを利用できます。詳細については、PostgreSQL のドキュメントの「[パーティションプルーニング](https://www.postgresql.org/docs/current/ddl-partitioning.html#DDL-PARTITION-PRUNING)」を参照してください。を参照してください。

### 不要なインデックスを削除する
<a name="wait-event.lw-lock-manager.actions.indexes"></a>

データベースには、未使用またはほとんど使用されないインデックスが含まれている可能性があります。その場合は、それらの削除を検討します。次のいずれかを実行します。
+ 不要なインデックスを見つける方法については、PostgreSQL wikiの「[未使用のインデックス](https://wiki.postgresql.org/wiki/Index_Maintenance#Unused_Indexes)」を参照してください。
+ PG コレクタを実行します。この SQL スクリプトは、データベース情報を収集し、統合 HTML レポートに表示します。「未使用のインデックス」セクションをチェックします。詳細については、AWSLabs GitHub リポジトリの「[PG コレクター](https://github.com/awslabs/pg-collector)」を参照してください。

### 高速パスロック用にクエリをチューニングする
<a name="wait-event.lw-lock-manager.actions.tuning"></a>

クエリで高速パスロックが使用されているかどうかを調べるには、`pg_locks`テーブルの`fastpath`列にクエリを実行します。クエリで高速パスロックを使用していない場合は、クエリあたりのリレーション数を 16 未満に減らしてください。

### 他の待機イベントに合わせてチューニングする
<a name="wait-event.lw-lock-manager.actions.other-waits"></a>

`LWLock:lock_manager`が上位待機のリストの第1位または 2 番目である場合、次の待機イベントもリストに表示されるかどうかを確認します。
+ `Lock:Relation`
+ `Lock:transactionid`
+ `Lock:tuple`

上記のイベントがリスト内で上位に表示される場合は、まずこれらの待機イベントのチューニングを検討してください。これらのイベントは、`LWLock:lock_manager`のドライバーになり得ます。

### ハードウェアのボトルネックを減らす
<a name="wait-event.lw-lock-manager.actions.hw-bottlenecks"></a>

CPU の枯渇や Amazon EBS 帯域幅の最大使用率など、ハードウェアのボトルネックが発生する可能性があります。このような場合は、ハードウェアのボトルネックを減らすことを検討してください。以下のアクションの場合を検討します。
+ インスタンスクラスをスケールアップします。
+ 大量の CPU とメモリを消費するクエリを最適化します。
+ アプリケーションロジックを変更します。
+ データをアーカイブします。

CPU、メモリ、および EBS ネットワーク帯域幅の詳細については、[Amazon RDS インスタンスタイプ](https://aws.amazon.com/rds/instance-types/)を参照してください。

### 接続プーラーを使用する
<a name="wait-event.lw-lock-manager.actions.pooler"></a>

アクティブな接続の総数が最大 vCPU を超えると、インスタンスタイプがサポートできるより多くの OS プロセスが CPU を必要とします。このような場合は、接続プールの使用またはチューニングを検討してください。インスタンスタイプの vCPUs の詳細については、「[Amazon RDS インスタンスタイプ](https://aws.amazon.com/rds/instance-types/)」を参照してください。

 接続プールの詳細については、次のリソースを参照してください。
+ [Amazon RDS Proxy ](rds-proxy.md)
+ [pgbouncer](http://www.pgbouncer.org/usage.html)
+ *PostgreSQL ドキュメント*の[接続プールとデータソース](https://www.postgresql.org/docs/7.4/jdbc-datasource.html)

### RDS for PostgreSQL バージョンのアップグレード
<a name="wait-event.lw-lock-manager.actions.pg-version"></a>

現在使用している RDS for PostgreSQL のバージョンが 12 より前のものであれば、バージョン 12 以降にアップグレードします。PostgreSQL バージョン 12 以降では、パーティションメカニズムが改良されています。バージョン12の詳細については、[PostgreSQL 12.0 リリースノート]( https://www.postgresql.org/docs/release/12.0/)を参照してください。RDS for PostgreSQL のアップグレードの詳細については、「[RDS for PostgreSQL DB エンジンのアップグレード](USER_UpgradeDBInstance.PostgreSQL.md)」を参照してください。

# LWLock:pg\$1stat\$1statements
<a name="apg-rpg-lwlockpgstat"></a>

LWLock:pg\$1stat\$1statements 待機イベントは、`pg_stat_statements` 拡張機能が SQL ステートメントを追跡するハッシュテーブルで排他的ロックを取得したときに発生します。これは以下のようなシナリオで発生します。
+ 追跡されるステートメントの数が設定された `pg_stat_statements.max` パラメータ値に達し、さらに多くのエントリを格納する必要がある場合、拡張機能は呼び出し数をソートし、最も実行されていないステートメントの 5% を削除し、ハッシュに残りのエントリを再入力します。
+ `pg_stat_statements` がディスク上の `pgss_query_texts.stat` ファイルに `garbage collection` 操作を実行し、ファイルを書き換えた場合。

**Topics**
+ [

## サポート対象エンジンバージョン
](#apg-rpg-lwlockpgstat.supported)
+ [

## Context
](#apg-rpg-lwlockpgstat.context)
+ [

## 待機時間が増加する原因の可能性
](#apg-rpg-lwlockpgstat.causes)
+ [

## アクション
](#apg-rpg-lwlockpgstat.actions)

## サポート対象エンジンバージョン
<a name="apg-rpg-lwlockpgstat.supported"></a>

 この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="apg-rpg-lwlockpgstat.context"></a>

**pg\$1stat\$1statements 拡張機能を理解する** – pg\$1stat\$1statements 拡張機能は、ハッシュテーブル内の SQL ステートメントの実行統計を追跡します。拡張機能は、`pg_stat_statements.max` パラメータで定義された制限まで SQL ステートメントを追跡します。このパラメータは、pg\$1stat\$1statements ビューの最大行数に対応する、追跡できるステートメントの最大数を決定します。

**ステートメント統計の永続性** – 拡張機能は、以下によってインスタンスのすべての再起動でステートメント統計を保持します。
+ pg\$1stat\$1statements.stat という名前のファイルにデータを書き込む
+ pg\$1stat\$1statements.save パラメータを使用して永続性の動作を制御する

pg\$1stat\$1statements.save の設定と動作。
+ on (デフォルト): 統計はシャットダウン時に保存され、サーバー起動時に再ロードされる
+ off: 統計はシャットダウン時に保存されず、サーバー起動時に再ロードされない

**クエリテキストストレージ** – 拡張機能は、追跡されたクエリのテキストを `pgss_query_texts.stat` という名前のファイルに保存します。このファイルは、ガベージコレクションが発生する前に、追跡されるすべての SQL ステートメントの平均サイズの 2 倍に増加する可能性があります。拡張機能では、クリーンアップオペレーションと `pgss_query_texts.stat` ファイルの書き換え中にハッシュテーブルに排他的ロックが必要です。

**ステートメントの割り当て解除プロセス** – 追跡されたステートメントの数が `pg_stat_statements.max` の制限に達し、新しいステートメントを追跡する必要がある場合、拡張機能は以下の処理を行います。
+ ハッシュテーブルで排他的ロック (LWLock:pg\$1stat\$1statements) を取得します。
+ 既存のデータをローカルメモリにロードします。
+ 呼び出しの数に基づいてクイックソートを実行します。
+ 最小呼び出しステートメント (下位 5%) を削除します。
+ ハッシュテーブルに残りのエントリを再入力します。

**ステートメントの割り当て解除のモニタリング** – PostgreSQL 14 以降では、pg\$1stat\$1statements\$1info ビューを使用してステートメントの割り当て解除をモニタリングできます。このビューには、新しいステートメントのスペースを確保するためにステートメントが割り当て解除された回数を示す dealloc 列が含まれています。

ステートメントの割り当て解除が頻繁に発生すると、ディスク上の `pgss_query_texts.stat` ファイルのガベージコレクションの頻度が高くなります。

## 待機時間が増加する原因の可能性
<a name="apg-rpg-lwlockpgstat.causes"></a>

`LWLock:pg_stat_statements` の待機時間が長くなる一般的な原因は次のとおりです。
+ アプリケーションで使用される一意のクエリの数の増加。
+ `pg_stat_statements.max` パラメータ値が、使用されている一意のクエリの数と比較して小さい。

## アクション
<a name="apg-rpg-lwlockpgstat.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。`LWLock:pg_stat_statements` イベントは、Amazon RDS Performance Insights を使用するか、ビュー `pg_stat_activity` のクエリで特定することができます。

次の `pg_stat_statements` パラメータを調整して追跡動作を制御し、LWLock:pg\$1stat\$1statements の待機イベントを減らします。

**Topics**
+ [

### pg\$1stat\$1statements.track パラメータを無効にする
](#apg-rpg-lwlockpgstat.actions.disabletrack)
+ [

### pg\$1stat\$1statements.max パラメータを増やす
](#apg-rpg-lwlockpgstat.actions.increasemax)
+ [

### pg\$1stat\$1statements.track\$1utility パラメータを無効にする
](#apg-rpg-lwlockpgstat.actions.disableutility)

### pg\$1stat\$1statements.track パラメータを無効にする
<a name="apg-rpg-lwlockpgstat.actions.disabletrack"></a>

LWLock:pg\$1stat\$1statements 待機イベントがデータベースのパフォーマンスに悪影響を及ぼし、`pg_stat_statements` ビューをさらに分析して根本原因を特定する前に迅速な対応が必要な場合は、`pg_stat_statements.track` パラメータを `none` に設定することで無効にできます。これにより、ステートメント統計の収集が無効になります。

### pg\$1stat\$1statements.max パラメータを増やす
<a name="apg-rpg-lwlockpgstat.actions.increasemax"></a>

ディスク上の `pgss_query_texts.stat` ファイルの割り当て解除を減らし、ガベージコレクションを最小限に抑えるため、`pg_stat_statements.max` パラメータの値を増やします。デフォルト値は `5,000` です。

**注記**  
`pg_stat_statements.max` パラメータは即時反映されません。これらのパラメータの変更を適用するには、DB インスタンスを再起動する必要があります。

### pg\$1stat\$1statements.track\$1utility パラメータを無効にする
<a name="apg-rpg-lwlockpgstat.actions.disableutility"></a>

pg\$1stat\$1statements ビューを分析して、`pg_stat_statements` によって追跡されるリソースを最も多く消費しているユーティリティコマンドを特定できます。

`pg_stat_statements.track_utility` パラメータは、SELECT、INSERT、UPDATE、DELETE、MERGE を除くすべてのコマンドを含むユーティリティコマンドをモジュールが追跡するかどうかを制御します。デフォルトでは、このパラメータは `on` に設定されます。

例えば、アプリケーションが本質的に一意である多くのセーブポイントクエリを使用する場合、ステートメントの割り当て解除が増加する可能性があります。これに対処するには、`pg_stat_statements.track_utility` パラメータを無効にして `pg_stat_statements` がセーブポイントクエリを追跡しないようにします。

**注記**  
`pg_stat_statements.track_utility` パラメータは変更後、即時反映されます。データベースインスタンスを再起動することなく、その値を変更できます。

**Example pg\$1stat\$1statements での一意のセーブポイントクエリの例**  <a name="savepoint-queries"></a>

```
                     query                       |       queryid       
-------------------------------------------------+---------------------
 SAVEPOINT JDBC_SAVEPOINT_495701                 | -7249565344517699703
 SAVEPOINT JDBC_SAVEPOINT_1320                   | -1572997038849006629
 SAVEPOINT JDBC_SAVEPOINT_26739                  |  54791337410474486
 SAVEPOINT JDBC_SAVEPOINT_1294466                |  8170064357463507593
 ROLLBACK TO SAVEPOINT JDBC_SAVEPOINT_65016      | -33608214779996400
 SAVEPOINT JDBC_SAVEPOINT_14185                  | -2175035613806809562
 SAVEPOINT JDBC_SAVEPOINT_45837                  | -6201592986750645383
 SAVEPOINT JDBC_SAVEPOINT_1324                   |  6388797791882029332
```

PostgreSQL 17 では、ユーティリティコマンドの追跡にいくつかの機能強化が導入されています。
+ セーブポイント名が定数として表示されるようになりました。
+ 2 フェーズコミットコマンドのグローバルトランザクション ID (GID) が定数として表示されるようになりました。
+ DEALLOCATE ステートメントの名前は定数として表示されます。
+ CALL パラメータが定数として表示されるようになりました。

# LWLock:SubtransSLRU (LWLock:SubtransControlLock)
<a name="wait-event.lwlocksubtransslru"></a>

`LWLock:SubtransSLRU` および `LWLock:SubtransBuffer` 待機イベントは、セッションがサブトランザクション情報の単純最小使用時間 (SLRU) キャッシュへのアクセスを待っていることを示します。これは、トランザクションの可視性と親子関係を決定するときに発生します。
+ `LWLock:SubtransSLRU`: プロセスは、サブトランザクションのシンプルな最も長い時間使われていない (SLRU) キャッシュへのアクセスを待っています。バージョン 13 より前の RDS for PostgreSQL では、この待機イベントは `SubtransControlLock` と呼ばれます。
+ `LWLock:SubtransBuffer`: プロセスは、サブトランザクションのシンプルな最も長い時間使われていない (SLRU) バッファの I/O を待っています。バージョン 13 より前の RDS for PostgreSQL では、この待機イベントは `subtrans` と呼ばれます。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.lwlocksubtransslru.supported)
+ [

## Context
](#wait-event.lwlocksubtransslru.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.lwlocksubtransslru.causes)
+ [

## アクション
](#wait-event.lwlocksubtransslru.actions)

## サポート対象エンジンバージョン
<a name="wait-event.lwlocksubtransslru.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="wait-event.lwlocksubtransslru.context"></a>

**サブトランザクションを理解する** – サブトランザクションは、PostgreSQL のトランザクション内のトランザクションです。ネストされたトランザクションとも呼ばれます。

サブトランザクションは通常、次の場合に作成されます。
+ `SAVEPOINT` コマンド
+ 例外ブロック (`BEGIN/EXCEPTION/END`)

サブトランザクションを使用すると、トランザクション全体に影響を与えることなく、トランザクションの一部をロールバックできます。これにより、トランザクション管理をきめ細かく制御できます。

**実装の詳細** – PostgreSQL は、メイントランザクション内のネストされた構造としてサブトランザクションを実装します。各サブトランザクションは独自のトランザクション ID を取得します。

実装の主な側面。
+ トランザクション ID は `pg_xact` で追跡されます。
+ 親子関係は `PGDATA` の `pg_subtrans` サブディレクトリに保存されます。
+ 各データベースセッションは、最大 `64` のアクティブなサブトランザクションを維持できます
+ この制限を超えると、サブトランザクションオーバーフローが発生します。サブトランザクション情報を取得するために、最も長い時間使われていない (SLRU) キャッシュにアクセスする必要があります

## 待機時間が増加する原因の可能性
<a name="wait-event.lwlocksubtransslru.causes"></a>

サブトランザクション SLRU 競合の一般的な原因は次のとおりです。
+ **SAVEPOINT および EXCEPTION 処理の過剰な使用** – `EXCEPTION` ハンドラーを使用した PL/pgSQL プロシージャは、例外が発生するかどうかにかかわらず、暗黙的なセーブポイントを自動的に作成します。各 `SAVEPOINT` は新しいサブトランザクションを開始します。1 つのトランザクションが 64 を超えるサブトランザクションを蓄積すると、サブトランザクション SLRU オーバーフローがトリガーされます。
+ **ドライバーと ORM の設定** – `SAVEPOINT` の使用は、アプリケーションコードで明示的で行うことも、ドライバー設定を通じて暗黙的に行うこともできます。一般的に使用される ORM ツールやアプリケーションフレームワークの多くは、ネストされたトランザクションをネイティブにサポートしています。以下は一般的な例です。
  + JDBC ドライバーパラメータ `autosave` を `always` または `conservative` に設定すると、各クエリの前にセーブポイントが生成されます。
  + Spring Framework トランザクション定義を `propagation_nested` に設定した場合。
  + `requires_new: true` が設定されている場合の Rails。
  + `session.begin_nested` を使用する場合の SQLAlchemy。
  + ネストされた `atomic()` ブロックを使用する場合の Django。
  + `Savepoint` を使用する場合の GORM。
  + ロールバックレベル設定がステートメントレベルのロールバックに設定されている場合の psqlODBC (例: `PROTOCOL=7.4-2`)。
+ **長時間実行されるトランザクションとサブトランザクションを伴う高同時ワークロード** – 同時ワークロードが高く、長時間実行されるトランザクションとサブトランザクション中にサブトランザクション SLRU オーバーフローが発生すると、PostgreSQL の競合が増加します。これは、`LWLock:SubtransBuffer` および `LWLock:SubtransSLRU` ロックの昇格された待機イベントとして現れます。

## アクション
<a name="wait-event.lwlocksubtransslru.actions"></a>

待機イベントの原因に応じたさまざまなアクションをお勧めします。一部のアクションは即時の打開策を提供しますが、他のアクションは調査と長期的な修正を必要とします。

**Topics**
+ [

### サブトランザクション使用状況のモニタリング
](#wait-event.lwlocksubtransslru.actions.monitor)
+ [

### メモリパラメータを設定する
](#wait-event.lwlocksubtransslru.actions.memory)
+ [

### 長時間のアクション
](#wait-event.lwlocksubtransslru.actions.longterm)

### サブトランザクション使用状況のモニタリング
<a name="wait-event.lwlocksubtransslru.actions.monitor"></a>

PostgreSQL バージョン 16.1 以降では、次のクエリを使用して、バックエンドごとのサブトランザクション数とオーバーフローステータスをモニタリングします。このクエリは、バックエンド統計をアクティビティ情報と結合して、サブトランザクションを使用しているプロセスを示します。

```
SELECT a.pid, usename, query, state, wait_event_type,
       wait_event, subxact_count, subxact_overflowed
FROM (SELECT id, pg_stat_get_backend_pid(id) pid, subxact_count, subxact_overflowed
      FROM pg_stat_get_backend_idset() id
           JOIN LATERAL pg_stat_get_backend_subxact(id) AS s ON true
     ) a
JOIN pg_stat_activity b ON a.pid = b.pid;
```

PostgreSQL バージョン 13.3 以降では、サブトランザクションキャッシュプレッシャーについて `pg_stat_slru` ビューをモニタリングします。次の SQL クエリは、Subtrans コンポーネントの SLRU キャッシュ統計を取得します。

```
SELECT * FROM pg_stat_slru WHERE name = 'Subtrans';
```

`blks_read` 値が一貫して増加すると、キャッシュされていないサブトランザクションのディスクアクセスが頻繁になり、SLRU キャッシュプレッシャーの可能性が示されます。

### メモリパラメータを設定する
<a name="wait-event.lwlocksubtransslru.actions.memory"></a>

PostgreSQL 17.1 以降では、`subtransaction_buffers` パラメータを使用してサブトランザクション SLRU キャッシュサイズを設定できます。次の設定例は、サブトランザクションバッファパラメータを設定する方法を示しています。

```
subtransaction_buffers = 128
```

このパラメータは、サブトランザクションコンテンツのキャッシュに使用される共有メモリの量を指定します (`pg_subtrans`)。単位なしで指定した場合、値は `BLCKSZ` バイトのブロックを表し、通常はそれぞれ 8KB です。例えば、値を 128 に設定すると、サブトランザクションキャッシュに 1MB (128 \$1 8kB) のメモリが割り当てられます。

**注記**  
このパラメータをクラスターレベルで設定することで、すべてのインスタンスの整合性を維持できます。特定のワークロード要件とインスタンスクラスに適した値をテストして調整します。パラメータの変更を有効にするには、ライターインスタンスを再起動する必要があります。

### 長時間のアクション
<a name="wait-event.lwlocksubtransslru.actions.longterm"></a>
+ **アプリケーションコードと設定の確認** – アプリケーションコードとデータベースドライバーの設定で、明示的および暗黙的な `SAVEPOINT` 使用状況とサブトランザクションの一般的な使用状況の両方を確認します。64 を超えるサブトランザクションを生成する可能性のあるトランザクションを特定します。
+ **セーブポイント使用量の削減** – トランザクションでのセーブポイントの使用を最小限に抑えます。
  + EXCEPTION ブロックを使用して PL/pgSQL の手順と関数を確認します。EXCEPTION ブロックは暗黙的なセーブポイントを自動的に作成し、サブトランザクションのオーバーフローにつながる可能性があります。各 EXCEPTION 句は、実行中に例外が実際に発生したかどうかに関係なく、サブトランザクションを作成します。  
**Example**  

    例 1: 問題のある EXCEPTION ブロックの使用

    次のコード例は、複数のサブトランザクションを作成する問題のある EXCEPTION ブロックの使用を示しています。

    ```
    CREATE OR REPLACE FUNCTION process_user_data()
    RETURNS void AS $$
    DECLARE
        user_record RECORD;
    BEGIN
        FOR user_record IN SELECT * FROM users LOOP
            BEGIN
                -- This creates a subtransaction for each iteration
                INSERT INTO user_audit (user_id, action, timestamp)
                VALUES (user_record.id, 'processed', NOW());
                
                UPDATE users 
                SET last_processed = NOW() 
                WHERE id = user_record.id;
                
            EXCEPTION
                WHEN unique_violation THEN
                    -- Handle duplicate audit entries
                    UPDATE user_audit 
                    SET timestamp = NOW() 
                    WHERE user_id = user_record.id AND action = 'processed';
            END;
        END LOOP;
    END;
    $$ LANGUAGE plpgsql;
    ```

    次の改善されたコード例では、例外処理の代わりに UPSERT を使用することで、サブトランザクションの使用を削減しています。

    ```
    CREATE OR REPLACE FUNCTION process_user_data()
    RETURNS void AS $$
    DECLARE
        user_record RECORD;
    BEGIN
        FOR user_record IN SELECT * FROM users LOOP
            -- Use UPSERT to avoid exception handling
            INSERT INTO user_audit (user_id, action, timestamp)
            VALUES (user_record.id, 'processed', NOW())
            ON CONFLICT (user_id, action) 
            DO UPDATE SET timestamp = NOW();
            
            UPDATE users 
            SET last_processed = NOW() 
            WHERE id = user_record.id;
        END LOOP;
    END;
    $$ LANGUAGE plpgsql;
    ```  
**Example**  

    例 2: STRICT 例外ハンドラー

    次のコード例は、NO\$1DATA\$1FOUND を使用した EXCEPTION 処理の問題を示しています。

    ```
    CREATE OR REPLACE FUNCTION get_user_email(p_user_id INTEGER)
    RETURNS TEXT AS $$
    DECLARE
        user_email TEXT;
    BEGIN
        BEGIN
            -- STRICT causes an exception if no rows or multiple rows found
            SELECT email INTO STRICT user_email 
            FROM users 
            WHERE id = p_user_id;
            
            RETURN user_email;
            
        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                RETURN 'Email not found';
        END;
    END;
    $$ LANGUAGE plpgsql;
    ```

    次の改善されたコード例では、例外処理の代わりに IF NOT FOUND を使用してサブトランザクションを回避します。

    ```
    CREATE OR REPLACE FUNCTION get_user_email(p_user_id INTEGER)
    RETURNS TEXT AS $$
    DECLARE
        user_email TEXT;
    BEGIN
         SELECT email INTO user_email 
         FROM users 
         WHERE id = p_user_id;
            
         IF NOT FOUND THEN
             RETURN 'Email not found';
         ELSE
             RETURN user_email;
         END IF;
    END;
    $$ LANGUAGE plpgsql;
    ```
  + JDBC ドライバー – `autosave` パラメータを `always` または `conservative` に設定すると、各クエリの前にセーブポイントが生成されます。`never` 設定がアプリケーションに受け入れられるかどうかを評価します。
  + PostgreSQL ODBC ドライバー (psqlODBC) — ロールバックレベル設定 (ステートメントレベルのロールバック用) は、ステートメントのロールバック機能を有効にするための暗黙的なセーブポイントを作成します。トランザクションレベルのロールバックがアプリケーションで許容されるかどうかを評価します。
  + ORM トランザクション設定を確認する
  + セーブポイントを必要としない代替エラー処理戦略を検討する
+ **トランザクション設計の最適化** – 過剰なネストを回避し、サブトランザクションオーバーフロー条件の可能性を減らすために、トランザクションを再構築します。
+ **長時間実行されるトランザクションの削減** – 長時間実行されるトランザクションでは、サブトランザクション情報を長く保持することで、サブトランザクションの問題が悪化する可能性があります。Performance Insights メトリクスをモニタリングし、アイドル状態のトランザクションを自動的に終了するように `idle_in_transaction_session_timeout` パラメータを設定します。
+ Performance Insights メトリクスのモニタリング – `idle_in_transaction_count` (トランザクション状態でアイドル状態のセッション数) や `idle_in_transaction_max_time` (アイドル状態にある最長時間のトランザクションの継続時間) などのメトリクスを追跡して、長時間実行されるトランザクションを検出します。
+ `idle_in_transaction_session_timeout` の設定 – 指定した期間後にアイドル状態のトランザクションを自動的に終了するように、パラメータグループにこのパラメータを設定します。
+ プロアクティブモニタリング – `LWLock:SubtransBuffer` および `LWLock:SubtransSLRU` 待機イベントの発生頻度をモニタリングし、サブトランザクション関連の競合が重大になる前に検出します。

# Timeout:PgSleep
<a name="wait-event.timeoutpgsleep"></a>

`Timeout:PgSleep`イベントは、サーバプロセスが`pg_sleep`関数を呼び出し、スリープタイムアウトの期限切れを待っているときに発生します。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.timeoutpgsleep.context.supported)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.timeoutpgsleep.causes)
+ [

## アクション
](#wait-event.timeoutpgsleep.actions)

## サポート対象エンジンバージョン
<a name="wait-event.timeoutpgsleep.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## 待機時間が増加する原因の可能性
<a name="wait-event.timeoutpgsleep.causes"></a>

この待機イベントは、アプリケーション、ストアド関数、またはユーザーが次のいずれかの関数を呼び出す SQL ステートメントを発行したときに発生します。
+ `pg_sleep`
+ `pg_sleep_for`
+ `pg_sleep_until`

前述の関数は、指定された秒数が経過するまで実行を遅らせます。例えば、`SELECT pg_sleep(1)` は 1 秒間一時停止します。詳細については、PostgreSQL のドキュメントの「[実行の遅延](https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-DELAY)」を参照してください。

## アクション
<a name="wait-event.timeoutpgsleep.actions"></a>

`pg_sleep`関数を実行していたステートメントを特定します。関数の使用が適切かどうかを判断します。

# Timeout:VacuumDelay
<a name="wait-event.timeoutvacuumdelay"></a>

`Timeout:VacuumDelay` イベントは、バキューム I/O のコスト制限を超え、バキュームプロセスがスリープ状態になったことを示します。バキュームオペレーションは、それぞれのコスト遅延パラメータで指定された期間停止し、その後動作を再開します。手動バキュームコマンドの場合、遅延は `vacuum_cost_delay` パラメータで指定されます。自動バキュームデーモンの場合、遅延は `autovacuum_vacuum_cost_delay parameter.` で指定されます。

**Topics**
+ [

## サポート対象エンジンバージョン
](#wait-event.timeoutvacuumdelay.context.supported)
+ [

## Context
](#wait-event.timeoutvacuumdelay.context)
+ [

## 待機時間が増加する原因の可能性
](#wait-event.timeoutvacuumdelay.causes)
+ [

## アクション
](#wait-event.timeoutvacuumdelay.actions)

## サポート対象エンジンバージョン
<a name="wait-event.timeoutvacuumdelay.context.supported"></a>

この待機イベント情報は、RDS for PostgreSQL のすべてのバージョンでサポートされています。

## Context
<a name="wait-event.timeoutvacuumdelay.context"></a>

PostgreSQL には、自動バキュームデーモンと手動バキュームコマンドがあります。自動バキュームプロセスは、RDS for PostgreSQL DB インスタンスでデフォルトで「オン」になっています。手動バキュームコマンドは、dead タプルのテーブルの削除や、新しい統計の生成など、必要に応じて使用されます。

バキューム処理中は、PostgreSQL では内部カウンターを使用して、システムがさまざまな I/O オペレーションを実行する際の推定コストを追跡します。カウンターがコスト制限パラメータで指定された値に達すると、そのオペレーションを実行するプロセスは、コスト遅延パラメータで指定された短時間の間スリープ状態になります。その後、カウンターをリセットしてオペレーションを続行します。

バキュームプロセスには、リソース消費量を調整するために使用できるパラメータがあります。自動バキュームコマンドと手動バキュームコマンドには、コスト制限値を設定するための独自のパラメータがあります。コスト遅延、つまり制限に達したときにバキュームをスリープ状態にする時間を指定する独自のパラメータもあります。このように、コスト遅延パラメータは、リソース消費のスロットリングメカニズムとして機能します。以下の一覧で、これらのパラメータの説明を参照できます。

**自動バキュームデーモンのスロットリングに影響するパラメータ**
+ `[autovacuum\$1vacuum\$1cost\$1limit](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-LIMIT)` – 自動バキュームオペレーションで使用するコスト制限値を指定します。このパラメータの設定を増やすと、バキュームプロセスが使用するリソースが増え、`Timeout:VacuumDelay` 待機イベントが減ります。
+ `[autovacuum\$1vacuum\$1cost\$1delay](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)` – 自動バキュームオペレーションで使用するコスト遅延値を指定します。デフォルト値は 2 ミリ秒です。遅延パラメータを 0 に設定すると、スロットリングメカニズムがオフになり、`Timeout:VacuumDelay` 待機イベントは表示されなくなります。

詳細については、「PostgreSQL のドキュメント」の「[Automatic Vacuuming](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)」(自動バキューム処理) を参照してください。

**手動バキュームプロセスのスロットリングに影響するパラメータ**
+ `vacuum_cost_limit` – バキューム処理をスリープ状態にするしきい値。デフォルトの制限値は 200 です。この数値は、さまざまなリソースが必要とする追加の I/O の累積コスト見積もりを表します。この値を増やすと、`Timeout:VacuumDelay` 待機イベントの数が減ります。
+ `vacuum_cost_delay` – バキュームのコスト制限に達したときに、バキュームプロセスがスリープになる時間。デフォルト設定は 0 で、この機能はオフになります。この機能を有効にするミリ秒数を整数値で指定できますが、デフォルト設定のままにしておくことをお勧めします。

`vacuum_cost_delay` パラメータの詳細については、PostgreSQL ドキュメントの「[リソース消費](https://www.postgresql.org/docs/current/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST)」を参照してください。

RDS for PostgreSQL で自動バキュームを設定し、使用する方法の詳細については、「[Amazon RDS for PostgreSQL での PostgreSQL 自動バキュームの使用](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md)」を参照してください。

## 待機時間が増加する原因の可能性
<a name="wait-event.timeoutvacuumdelay.causes"></a>

`Timeout:VacuumDelay` は、バキュームのスリープ時間を制御するコスト制限パラメータ設定 (`vacuum_cost_limit`、`autovacuum_vacuum_cost_limit`) と、コスト遅延パラメータ (`vacuum_cost_delay`、`autovacuum_vacuum_cost_delay`) のバランスの影響を受けます。コスト制限のパラメータ値を上げると、バキュームがスリープ状態になる前に利用できるリソースが増えます。その結果、`Timeout:VacuumDelay` 待機イベントが少なくなります。いずれかの遅延パラメータを増やすと、これまでよりも頻繁に、長期間 `Timeout:VacuumDelay` 待機イベントが発生します。

`autovacuum_max_workers` パラメータ設定により、`Timeout:VacuumDelay` の数を増やすこともできます。自動バキュームワーカープロセスを追加するごとに内部カウンターメカニズムに影響を与えるため、単一の自動バキュームワーカープロセスを使用する場合よりも早く上限に達する場合があります。コスト制限に早く達するとコスト遅延がより頻繁に発生し、結果的に `Timeout:VacuumDelay` 待機イベントが増えます。詳細については、PostgreSQL ドキュメントの「[autovacuum\$1max\$1workers](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-MAX-WORKERS)」を参照してください。

バキュームが大きなオブジェクトの処理を完了するまでに時間がかかることがあるため、500 GB 以上の大きなオブジェクトでもこの待機イベントが発生します。

## アクション
<a name="wait-event.timeoutvacuumdelay.actions"></a>

想定どおりにバキュームオペレーションが完了すれば、修復は不要です。つまり、この待機イベントは、必ずしも問題を示すわけではありません。これは、処理を完了する必要のある他のプロセスにリソースを割り当てることができるように、バキュームが遅延パラメータで指定された時間だけスリープ状態になっていることを示しています。

バキュームオペレーションをより早く完了させる場合は、遅延パラメータを下げることができます。これにより、バキュームのスリープ時間が短縮されます。