

# 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`」に最近変更が加えられました。