

# Amazon RDS for PostgreSQL での PostgreSQL 自動バキュームの使用
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum"></a>

autovacuum 機能を使用して、PostgreSQL DB インスタンスの状態を維持することを強くお勧めします。autovacuum は、VACUUM コマンドと ANALYZE コマンドのスタートを自動化します。自動バキュームが、多数のタプルが挿入、更新、または削除されたテーブルを確認します。確認後、自動バキュームは PostgreSQL データベースから古いデータやタプルを削除することで、ストレージを再利用します。

デフォルトの PostgreSQL DB パラメータグループのいずれかを使用して作成した RDS for PostgreSQL DB インスタンスでは、デフォルトで自動バキュームがオンになっています。autovacuum 機能に関連するその他の設定パラメータもデフォルトで設定されます。これらのデフォルト値は汎用的であるため、特定のワークロードに対して、autovacuum 機能に関連付けられているパラメータの一部をチューニングすることには利点があります。

次に、autovacuum の詳細と、RDS for PostgreSQL DB インスタンスでそのパラメータの一部をチューニングする方法について説明します。概要については、「[PostgreSQL を使用するためのベストプラクティス](CHAP_BestPractices.md#CHAP_BestPractices.PostgreSQL)」を参照してください。

**Topics**
+ [autovacuum のメモリを割り当てる](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory)
+ [トランザクション ID の循環の可能性を減らす](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming)
+ [データベース内のテーブルにバキューム処理が必要かどうかの判別](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.NeedVacuuming.md)
+ [現在 autovacuum の対象となっているテーブルの判別](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.EligibleTables.md)
+ [Autovacuum が現在実行されているかどうかと実行されている時間の判別](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AutovacuumRunning.md)
+ [手動バキュームフリーズの実行](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze.md)
+ [autovacuum の実行中にテーブルのインデックスを再作成する](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Reindexing.md)
+ [大きなインデックスを使った autovacuum の管理](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.md)
+ [autovacuum に影響を与えるその他のパラメータ](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.OtherParms.md)
+ [テーブルレベルの autovacuum パラメータを設定する](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.TableParameters.md)
+ [自動バキュームおよびバキュームアクティビティのログ記録](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Logging.md)
+ [無効なデータベースでの自動バキュームの動作を理解する](appendix.postgresql.commondbatasks.autovacuumbehavior.md)
+ [RDS for PostgreSQL で積極的なバキュームのブロック要因を特定して解決する](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.md)

## autovacuum のメモリを割り当てる
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.WorkMemory"></a>

autovacuum のパフォーマンスに影響を与える最も重要なパラメータの 1 つは、[https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM) パラメータです。RDS for PostgreSQL バージョン 14 以前では、`autovacuum_work_mem` パラメータは -1 に設定されており、`maintenance_work_mem` の設定が代わりに使用されていることを示します。他のすべてのバージョンでは、`autovacuum_work_mem` は GREATEST(\$1DBInstanceClassMemory/32768\$1, 65536) によって決定されます。

手動バキュームオペレーションは常に `maintenance_work_mem` 設定を使用し、デフォルト設定は GREATEST(\$1DBInstanceClassMemory/63963136\$11024\$1, 65536) です。また、より的を絞った手動 `VACUUM` オペレーションを実現するために、`SET` のコマンドを使用してセッションレベルで調整することもできます。

`autovacuum_work_mem` は、インデックスをバキュームするためのデッドタプル (`pg_stat_all_tables.n_dead_tup`) の識別子を保持するため、autovacuum のメモリを決定します。

計算を実行して `autovacuum_work_mem` パラメータの値を決定するときは、次の点に注意してください。
+ パラメータの設定値が低すぎると、バキューム処理が完了するまでにテーブルを複数回スキャンすることが必要になる場合があります。このような複数のスキャンは、パフォーマンスに悪影響を及ぼすことがあります。より大きなインスタンスでは、`maintenance_work_mem` または `autovacuum_work_mem` を少なくとも 1 GB に設定することで、デッドタプル数が多いテーブルをバキュームするためのパフォーマンスが向上します。ただし、PostgreSQL バージョン 16 以前では、バキュームのメモリ使用量は 1 GB に制限されています。これは、1 回のパスで約 1 億 7,900 万個のデッドタプルを処理するのに十分な量です。テーブルのデッドタプルがこれよりも多い場合、バキュームはテーブルのインデックスを複数回通過させる必要があり、所要時間が大幅に増加します。PostgreSQL バージョン 17 以降、1 GB の制限はなく、自動バキュームは基数ツリーを使用して 1 億 7,900 万を超えるタプルを処理できます。

  タプル識別子のサイズは 6 バイトです。テーブルのインデックスのバキュームに必要なメモリを推定するには、`pg_stat_all_tables.n_dead_tup` をクエリしてデッドタプル数を求め、この数に 6 を掛けて、1 回のパスでインデックスをバキュームするのに必要なメモリを決定します。以下のクエリを使用できます。

  ```
  SELECT
      relname AS table_name,
      n_dead_tup,
      pg_size_pretty(n_dead_tup * 6) AS estimated_memory
  FROM
      pg_stat_all_tables
  WHERE
      relname = 'name_of_the_table';
  ```
+ `autovacuum_work_mem` パラメータは、`autovacuum_max_workers` パラメータと連動して機能します。`autovacuum_max_workers` 間の各ワーカーは、割り当てたメモリを使用できます。小さいテーブルが多数ある場合、`autovacuum_max_workers` の割り当てを増やして `autovacuum_work_mem` の割り当てを減らします。大きなテーブル (100 GB 以上) がある場合は、メモリの割り当てを増やしてワーカープロセス数を減らします。最も大きいテーブルを正常に処理するには、十分なメモリを割り当てる必要があります。したがって、ワーカープロセスとメモリの組み合わせが、割り当てるメモリの合計と等しくなることを確認してください。

## トランザクション ID の循環の可能性を減らす
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming"></a>

autovacuum に関連するパラメータグループの設定は、トランザクション ID の循環を防ぐほどは排除率が高くない場合があります。この問題に対処するために、RDS for PostgreSQL には autovacuum パラメータ値を自動的に適応させるメカニズムが用意されています。*適応型 autovacuum* は、RDS for PostgreSQL の機能です。[トランザクション ID の循環](https://www.postgresql.org/docs/current/static/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)に関する詳しい説明については、PostgreSQL ドキュメントを参照してください。

適応型 autovacuum は、動的パラメータ `rds.adaptive_autovacuum` が ON に設定されている RDS for PostgreSQL インスタンスでは、デフォルトでオンになります。この設定をオンにしておくことを強くお勧めします。ただし、autovacuum パラメータのアダプティブチューニングをオフにする場合は、`rds.adaptive_autovacuum` パラメータを 0 または OFF に設定します。

トランザクション ID の循環は、Amazon RDS で autovacuum パラメータをチューニングした後でも発生する場合があります。トランザクション ID の循環に対して Amazon CloudWatch アラームを実装することをお勧めします。詳細については、AWS データベースブログの記事「[Implement an early warning system for transaction ID wraparound in RDS for PostgreSQL](https://aws.amazon.com/blogs/database/implement-an-early-warning-system-for-transaction-id-wraparound-in-amazon-rds-for-postgresql/)」(RDS for PostgreSQL でトランザクション ID の循環に早期警告システムを実装する) を参照してください。

自動バキュームパラメータのアダプティブチューニングをオンにすると、CloudWatch メトリクス `MaximumUsedTransactionIDs` が `autovacuum_freeze_max_age` パラメータの値または 500,000,000 のいずれか大きいほうに達したときに、Amazon RDS で自動バキュームパラメータの調整が開始されます。

テーブルでトランザクション ID の循環の傾向が続く場合、Amazon RDS では自動バキュームパラメータの調整が続行されます。続行される調整ごとに、循環を避けるために autovacuum に割り当てられる専用のリソースが増えます。Amazon RDS は、以下の autovacuum 関連のパラメータを更新します。
+ [autovacuum\$1vacuum\$1cost\$1delay](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)
+ [ autovacuum\$1vacuum\$1cost\$1limit](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-LIMIT)
+  [https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM](https://www.postgresql.org/docs/current/runtime-config-resource.html#GUC-AUTOVACUUM-WORK-MEM) 
+  [autovacuum\$1naptime](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html#GUC-AUTOVACUUM-NAPTIME) 

これらのパラメータが RDS で変更されるのは、新しい値で autovacuum による排除率が高くなる場合に限られます。パラメータは、DB インスタンスのメモリで変更されます。パラメータグループの値は変更されません。現在のメモリ内の設定を確認するには、PostgreSQL の [SHOW](https://www.postgresql.org/docs/current/sql-show.html) SQL コマンドを使用します。

これらの自動バキュームパラメータのいずれかが Amazon RDS で変更されると、影響を受ける DB インスタンスでイベントが生成されます。このイベントは、AWS マネジメントコンソール や Amazon RDS API を介して表示できます。CloudWatch メトリクス `MaximumUsedTransactionIDs` がしきい値より低い値に戻ると、Amazon RDS はメモリ内の自動バキューム関連のパラメータをリセットして、パラメータグループで指定されている値に戻します。次に、この変更に対応する別のイベントが生成されます。

# データベース内のテーブルにバキューム処理が必要かどうかの判別
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.NeedVacuuming"></a>

次のクエリを使用して、データベース内のフリーズしていないトランザクションの数を表示できます。データベースの `datfrozenxid` 行の `pg_database` 列は、そのデータベースに表示されている正常なトランザクション ID の下限です。この列は、データベース内のテーブルあたりの `relfrozenxid` 値の最小数です。

```
SELECT datname, age(datfrozenxid) FROM pg_database ORDER BY age(datfrozenxid) desc limit 20;
```

例えば、前述のクエリの実行結果は以下のようになります。

```
datname    | age
mydb       | 1771757888
template0  | 1721757888
template1  | 1721757888
rdsadmin   | 1694008527
postgres   | 1693881061
(5 rows)
```

データベースのトランザクション ID 数が 20 億に達すると、トランザクション ID (XID) の循環が発生し、データベースは読み取り専用になります。このクエリを使用してメトリクスを生成し、1 日に数回実行できます。デフォルトでは、autovacuum は保持するトランザクション数が 200,000,000 以下になるように設定されます ()。[https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-FREEZE-MAX-AGE](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-FREEZE-MAX-AGE)

サンプルモニタリング戦略は次のようになります。
+ `autovacuum_freeze_max_age` の値を 2 億トランザクションに設定します。
+ テーブルのフリーズしていないトランザクション数が 5 億に達すると、重要度が低いアラームがトリガーされます。これは無効な値ではありませんが、autovacuum が遅れていることを示している場合があります。
+ テーブルのトランザクション数が 10 億に達した場合は、対処を要するアラームとして扱う必要があります。一般的に、パフォーマンス上の理由から、トランザクション数は `autovacuum_freeze_max_age` に近い値にしてください。以下の推奨事項を使用して調査することをお勧めします。
+ テーブルのバキューム処理されていないトランザクション数が 15 億に達すると、重要度が高いアラームがトリガーされます。データベースでトランザクション ID をどれだけ速く使用するかによりますが、このアラームは、システムに autovacuum を実行する時間がないことを示している場合があります。この場合は、この問題を早急に解決することをお勧めします。

テーブルのサイズがこれらのしきい値を頻繁に超える場合は、自動バキュームパラメータをさらに変更します。デフォルトでは、手動で VACUUM (コストベースの遅延が無効) を使用するほうが、デフォルトの autovacuum を使用するより排除率が高くなりますが、システム全体に与える負担が増えます。

次の構成を推奨します。
+ この場合、最も古いトランザクションの経過時間を認識できるように、モニタリングメカニズムをオンにしてください。

  トランザクション ID の循還について警告するプロセスを作成する方法については、AWS のデータベースブログの記事「[Amazon RDS for PostgreSQL でトランザクション ID の循環に早期警告システムを実装する](https://aws.amazon.com/blogs/database/implement-an-early-warning-system-for-transaction-id-wraparound-in-amazon-rds-for-postgresql/)」を参照してください。
+ 処理の多いテーブルでは、autovacuum の使用に加えて、メンテナンスウィンドウ中に手動でバキュームフリーズを定期的に実行してください。手動バキュームフリーズの実行については、「[手動バキュームフリーズの実行](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze.md)」を参照してください。

# 現在 autovacuum の対象となっているテーブルの判別
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.EligibleTables"></a>

多くの場合、1 つ以上のテーブルにバキューム処理が必要です。`relfrozenxid` の値が `autovacuum_freeze_max_age` のトランザクション数を超えているテーブルは、常に autovacuum の処理対象となります。それ以外の場合、前回の VACUUM 以降「古い」とされたタプルの数が「バキュームしきい値」を超えると、テーブルがバキューム処理されます。

[autovacuum しきい値](https://www.postgresql.org/docs/current/static/routine-vacuuming.html#AUTOVACUUM)は、次のように定義されます。

```
Vacuum-threshold = vacuum-base-threshold + vacuum-scale-factor * number-of-tuples
```

ここで、`vacuum base threshold` は `autovacuum_vacuum_threshold`、`vacuum scale factor` は `autovacuum_vacuum_scale_factor`、`number of tuples` は `pg_class.reltuples` です。

データベースに接続しているときに、次のクエリを実行し、自動バキュームがバキューム処理の対象と見なしているテーブルのリストを表示します。

```
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)
ORDER BY age(relfrozenxid) DESC LIMIT 50;
```

# Autovacuum が現在実行されているかどうかと実行されている時間の判別
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AutovacuumRunning"></a>

テーブルを手動でバキューム処理する必要がある場合、必ず自動バキュームが現在実行されているかどうか判別してください。実行されている場合、さらに効率的に実行されるようにパラメータを調整するか、自動バキュームを一時的にオフに切り替えて VACUUM を手動で実行できるようにする必要がある場合があります。

次のクエリを使用して、autovacuum が実行中か、どのくらいの時間実行中か、また別のセッションの待機中かを判別します。

```
SELECT datname, usename, pid, state, wait_event, current_timestamp - xact_start AS xact_runtime, query
FROM pg_stat_activity 
WHERE upper(query) LIKE '%VACUUM%' 
ORDER BY xact_start;
```

クエリが実行されると、次のような出力が表示されます。

```
 datname | usename  |  pid  | state  | wait_event |      xact_runtime       | query  
 --------+----------+-------+--------+------------+-------------------------+--------------------------------------------------------------------------------------------------------
 mydb    | rdsadmin | 16473 | active |            | 33 days 16:32:11.600656 | autovacuum: VACUUM ANALYZE public.mytable1 (to prevent wraparound)
 mydb    | rdsadmin | 22553 | active |            | 14 days 09:15:34.073141 | autovacuum: VACUUM ANALYZE public.mytable2 (to prevent wraparound)
 mydb    | rdsadmin | 41909 | active |            | 3 days 02:43:54.203349  | autovacuum: VACUUM ANALYZE public.mytable3
 mydb    | rdsadmin |   618 | active |            | 00:00:00                | SELECT datname, usename, pid, state, wait_event, current_timestamp - xact_start AS xact_runtime, query+
         |          |       |        |            |                         | FROM pg_stat_activity                                                                                 +
         |          |       |        |            |                         | WHERE query like '%VACUUM%'                                                                           +
         |          |       |        |            |                         | ORDER BY xact_start;                                                                                  +
```

いくつかの問題が原因で autovacuum セッションの実行が長期間 (複数日) に渡る場合があります。最もよくある問題は、[https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) パラメータ値で設定されたテーブルのサイズまたは更新速度が小さすぎることです。

次の計算式を使用して、`maintenance_work_mem` パラメータ値を設定することをお勧めします。

```
GREATEST({DBInstanceClassMemory/63963136*1024},65536)
```

実行時間が短い autovacuum セッションは、以下の問題を示している可能性もあります。
+ ワークロード用の `autovacuum_max_workers` が十分ではないことを示している場合があります。この場合は、ワーカーの数を指定する必要があります。
+ インデックスの破損を示している場合があります (自動バキュームがクラッシュし、同じリレーションで再起動されますが進行はありません)。この場合は、手動 `vacuum freeze verbose table` を実行して正確な原因を確認します。

# 手動バキュームフリーズの実行
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze"></a>

バキュームプロセスが既に実行されているテーブルで、手動バキュームを実行できます。これは、トランザクション数が 20 億に近づいている (または、モニタリングしているしきい値を上回った) テーブルに気付いた場合に役立ちます。

次の手順はガイドラインであり、プロセスにはいくつかのバリエーションがあります。例えば、テスト時に、[https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) パラメータの設定値が小さすぎて、テーブルに早急な対処が必要であることに気づいたとします。ただし、今はインスタンスをバウンスしたくない場合があります。前のセクションのクエリを使用することで、問題のあるテーブルを判別し、長時間実行されている autovacuum セッションを確認できます。`maintenance_work_mem` パラメータ設定の変更が必要であることがわかっていても、すぐに対処して問題のテーブルにバキューム処理を実行する必要があります。このような場合、次の手順で対応します。

**バキュームフリーズを手動で実行するには**

1. バキュームを実行するテーブルを含むデータベースへのセッションを 2 つ開きます。2 番目のセッションで、接続が中断された場合にセッションを維持する「screen」または他のユーティリティを使用します。

1. セッション 1 で、テーブルで実行されている自動バキュームセッションのプロセス ID (PID) を取得します。

   次のクエリを実行し、autovacuum セッションの PID を取得します。

   ```
   SELECT datname, usename, pid, current_timestamp - xact_start 
   AS xact_runtime, query
   FROM pg_stat_activity WHERE upper(query) LIKE '%VACUUM%' ORDER BY 
   xact_start;
   ```

1. セッション 2 で、このオペレーションに必要なメモリの量を計算します。この例では、このオペレーションに最大 2GB のメモリを使用できると決めたため、現在のセッションの [https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE-WORK-MEM) を 2GB に設定します。

   ```
   SET maintenance_work_mem='2 GB';
   SET
   ```

1. セッション 2 で、テーブルに対して `vacuum freeze verbose` コマンドを発行します。現在のところ PostgreSQL には進行状況レポートがないため、verbose 設定はアクティビティを確認するのに役立ちます。

   ```
   \timing on
   Timing is on.
   vacuum freeze verbose pgbench_branches;
   ```

   ```
   INFO:  vacuuming "public.pgbench_branches"
   INFO:  index "pgbench_branches_pkey" now contains 50 row versions in 2 pages
   DETAIL:  0 index row versions were removed.
   0 index pages have been deleted, 0 are currently reusable.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   INFO:  index "pgbench_branches_test_index" now contains 50 row versions in 2 pages
   DETAIL:  0 index row versions were removed.
   0 index pages have been deleted, 0 are currently reusable.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   INFO:  "pgbench_branches": found 0 removable, 50 nonremovable row versions 
        in 43 out of 43 pages
   DETAIL:  0 dead row versions cannot be removed yet.
   There were 9347 unused item pointers.
   0 pages are entirely empty.
   CPU 0.00s/0.00u sec elapsed 0.00 sec.
   VACUUM
   Time: 2.765 ms
   ```

1. セッション 1 で、自動バキュームがバキュームセッションをブロックしていた場合、`pg_stat_activity` は、バキュームセッションを待機中であること (`T`) を示します。この場合は、次のように自動バキュームプロセスを終了します。

   ```
   SELECT pg_terminate_backend('the_pid'); 
   ```
**注記**  
Amazon RDS の一部の下位バージョンでは、前述のコマンドを使用して自動バキュームプロセスを終了できず、次のエラーで失敗します: `ERROR: 42501: must be a superuser to terminate superuser process LOCATION: pg_terminate_backend, signalfuncs.c:227`。

   この時点で、セッションがスタートされます。このテーブルは作業リストの一番上にあると思われるため、自動バキュームは即座に再開します。

1. セッション 2 で `vacuum freeze verbose` コマンドを開始し、セッション 1 で自動バキュームプロセスを終了します。

# autovacuum の実行中にテーブルのインデックスを再作成する
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Reindexing"></a>

インデックスが破損した場合、autovacuum はテーブルの処理を続けますが失敗します。この状況で手動バキュームを試みると、次のようなエラーメッセージが表示されます。

```
postgres=>  vacuum freeze pgbench_branches;
ERROR: index "pgbench_branches_test_index" contains unexpected 
   zero page at block 30521
HINT: Please REINDEX it.
```

インデックスが破損しているときに、自動バキュームをテーブルで実行しようとすると、既に実行中の自動バキュームセッションと競合します。「[REINDEX](https://www.postgresql.org/docs/current/static/sql-reindex.html)」コマンドを発行する場合は、テーブルに対する排他ロックを取り除きます。書き込みオペレーションがブロックされ、この特定のインデックスを使用する読み込みオペレーションもブロックされます。

**autovacuum がテーブルに対して実行されているときにテーブルのインデックスを再作成するには**

1. バキュームを実行するテーブルを含むデータベースへのセッションを 2 つ開きます。2 番目のセッションで、接続が中断された場合にセッションを維持する「screen」または他のユーティリティを使用します。

1. セッション 1 で、テーブルを実行している autovacuum セッションの PID を取得します。

   次のクエリを実行し、autovacuum セッションの PID を取得します。

   ```
   SELECT datname, usename, pid, current_timestamp - xact_start 
   AS xact_runtime, query
   FROM pg_stat_activity WHERE upper(query) like '%VACUUM%' ORDER BY 
   xact_start;
   ```

1. セッション 2 で、reindex コマンドを発行します。

   ```
   \timing on
   Timing is on.
   reindex index pgbench_branches_test_index;
   REINDEX
     Time: 9.966 ms
   ```

1. セッション 1 で、自動バキュームがプロセスをブロックしていた場合、`pg_stat_activity` で、バキュームセッションの [waiting] (待機) が「T」であることを確認できます。この場合、自動バキュームプロセスを終了します。

   ```
   SELECT pg_terminate_backend('the_pid');
   ```

   この時点で、セッションがスタートされます。このテーブルは作業リストの一番上にあると思われるため、autovacuum が即座に再開される点に注意することが重要です。

1. セッション 2 で コマンドを開始し、セッション 1 で自動バキュームプロセスを終了します。

# 大きなインデックスを使った autovacuum の管理
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes"></a>

操作の一環として、*autovacuum* はテーブル上で実行している間にいくつかの[バキュームフェーズ](https://www.postgresql.org/docs/current/progress-reporting.html#VACUUM-PHASES)を実行します。テーブルをクリーンアップする前に、まずすべてのインデックスがバキューム処理されます。複数の大きなインデックスを削除する場合、このフェーズではかなりの時間とリソースを消費します。したがって、ベストプラクティスとして、テーブル上のインデックスの数を制御し、未使用のインデックスを削除してください。

このプロセスでは、まずインデックス全体のサイズを確認します。次に、次の例に示すように、削除できるインデックスがあるかどうかを確認します。

**テーブルとそのインデックスのサイズを確認するには**

```
postgres=> select pg_size_pretty(pg_relation_size('pgbench_accounts'));
pg_size_pretty
6404 MB
(1 row)
```

```
postgres=> select pg_size_pretty(pg_indexes_size('pgbench_accounts'));
pg_size_pretty
11 GB
(1 row)
```

この例では、インデックスのサイズはテーブルよりも大きくなっています。この違いにより、インデックスが肥大化したり使用されなかったりするため、パフォーマンスの問題が発生し、自動バキュームや挿入オペレーションに影響する可能性があります。

**未使用のインデックスを確認するには**

[https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-INDEXES-VIEW](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ALL-INDEXES-VIEW) ビューを使用すると、`idx_scan` 列でインデックスがどのくらいの頻度で使用されているかを確認できます。次の例では、未使用のインデックスに `0` の `idx_scan` 値があります

```
postgres=> select * from pg_stat_user_indexes where relname = 'pgbench_accounts' order by idx_scan desc;
    
relid  | indexrelid | schemaname | relname          | indexrelname          | idx_scan | idx_tup_read | idx_tup_fetch
-------+------------+------------+------------------+-----------------------+----------+--------------+---------------
16433  | 16454      | public     | pgbench_accounts | index_f               | 6        | 6            | 0
16433  | 16450      | public     | pgbench_accounts | index_b               | 3        | 199999       | 0
16433  | 16447      | public     | pgbench_accounts | pgbench_accounts_pkey | 0        | 0            | 0
16433  | 16452      | public     | pgbench_accounts | index_d               | 0        | 0            | 0
16433  | 16453      | public     | pgbench_accounts | index_e               | 0        | 0            | 0
16433  | 16451      | public     | pgbench_accounts | index_c               | 0        | 0            | 0
16433  | 16449      | public     | pgbench_accounts | index_a               | 0        | 0            | 0
(7 rows)
```

```
postgres=> select schemaname, relname, indexrelname, idx_scan from pg_stat_user_indexes where relname = 'pgbench_accounts' order by idx_scan desc;
    
schemaname  | relname          | indexrelname          | idx_scan
------------+------------------+-----------------------+----------
public      | pgbench_accounts | index_f               | 6
public      | pgbench_accounts | index_b               | 3
public      | pgbench_accounts | pgbench_accounts_pkey | 0
public      | pgbench_accounts | index_d               | 0
public      | pgbench_accounts | index_e               | 0
public      | pgbench_accounts | index_c               | 0
public      | pgbench_accounts | index_a               | 0
(7 rows)
```

**注記**  
これらの統計情報は、統計がリセットされた時点から増加します。例えば、あるビジネス四半期末にのみ使用される、または特定のレポートにのみ使用されるインデックスがあるとします。統計がリセットされてから、このインデックスが使用されていない可能性があります。詳細については、「[統計関数](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-STATS-FUNCTIONS)」を参照してください。一意性を保証するために使用されるインデックスはスキャンされないため、未使用のインデックスとして識別しないでください。未使用のインデックスを特定するには、アプリケーションとそのクエリに関する深い知識が必要です。

データベースの統計が最後にリセットされた日時を確認するには、[ https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW]( https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-DATABASE-VIEW) を使用してください。

```
postgres=> select datname, stats_reset from pg_stat_database where datname = 'postgres';
    
datname   | stats_reset
----------+-------------------------------
postgres  | 2022-11-17 08:58:11.427224+00
(1 row)
```

## テーブルをできるだけ早くバキューム処理する
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.Executing"></a>

**RDS for PostgreSQL 12 以上**

大きなテーブルにインデックスが多すぎる場合、DB インスタンスがトランザクション ID ラップアラウンド (XID) に近づいている可能性があります。これは XID カウンターが 0 にラップアラウンドするタイミングです。チェックを外したままにすると、この状況では、データが失われる可能性があります。ただし、インデックスをクリーンアップせずにテーブルをすばやくバキューム処理できます。RDS for PostgreSQL 12 以上では、[https://www.postgresql.org/docs/current/sql-vacuum.html](https://www.postgresql.org/docs/current/sql-vacuum.html) 句で VACUUM を使用することができます。

```
postgres=> VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) pgbench_accounts;
        
INFO: vacuuming "public.pgbench_accounts"
INFO: table "pgbench_accounts": found 0 removable, 8 nonremovable row versions in 1 out of 819673 pages
DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 7517
Skipped 0 pages due to buffer pins, 0 frozen pages.
CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s.
```

自動バキュームセッションが既に実行されている場合、手動 VACUUM を開始するにはセッションを終了する必要があります。手動バキュームフリーズの実行については、「[手動バキュームフリーズの実行](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.VacuumFreeze.md)」を参照してください。

**注記**  
インデックスのクリーンアップを定期的にスキップすると、インデックスが肥大化し、スキャンのパフォーマンスが低下します。インデックスはデッド行を保持し、テーブルはデッドラインポインタを保持します。その結果、`pg_stat_all_tables.n_dead_tup` は autovacuum またはインデックスクリーンアップを含む手動 VACUUM が実行されるまで増加します。ベストプラクティスとして、この手順は、トランザクション ID の循環を防ぐためにのみ使用してください。

**RDS for PostgreSQL 11 以降**

ただし、RDS for PostgreSQL 11 以前のバージョンでは、バキューム処理をより速く完了させる唯一の方法は、テーブルのインデックス数を減らすことです。インデックスを削除すると、クエリプランに影響する可能性があります。未使用のインデックスを最初に削除し、XID の循環が間近になったらインデックスを削除することをお勧めします。バキューム処理が完了したら、これらのインデックスを再作成できます。

# autovacuum に影響を与えるその他のパラメータ
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.OtherParms"></a>

次のクエリは、autovacuum とその動作に直接影響を与えるパラメータのいくつかについて値を表示します。[autovacuum パラメータ](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html)の詳細については、PostgreSQL のドキュメントを参照してください。

```
SELECT name, setting, unit, short_desc
FROM pg_settings
WHERE name IN (
'autovacuum_max_workers',
'autovacuum_analyze_scale_factor',
'autovacuum_naptime',
'autovacuum_analyze_threshold',
'autovacuum_analyze_scale_factor',
'autovacuum_vacuum_threshold',
'autovacuum_vacuum_scale_factor',
'autovacuum_vacuum_threshold',
'autovacuum_vacuum_cost_delay',
'autovacuum_vacuum_cost_limit',
'vacuum_cost_limit',
'autovacuum_freeze_max_age',
'maintenance_work_mem',
'vacuum_freeze_min_age');
```

これらはすべて autovacuum に影響を与えますが、最も重要なものは以下のとおりです。
+ [maintenance\$1work\$1mem](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#GUC-MAINTENANCE_WORK_MEM)
+ [autovacuum\$1freeze\$1max\$1age](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-FREEZE-MAX-AGE)
+ [autovacuum\$1max\$1workers](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-MAX-WORKERS)
+ [autovacuum\$1vacuum\$1cost\$1delay](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-DELAY)
+ [ autovacuum\$1vacuum\$1cost\$1limit](https://www.postgresql.org/docs/current/static/runtime-config-autovacuum.html#GUC-AUTOVACUUM-VACUUM-COST-LIMIT)

# テーブルレベルの autovacuum パラメータを設定する
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.TableParameters"></a>

自動バキューム関連の[ストレージパラメータ](https://www.postgresql.org/docs/current/static/sql-createtable.html#SQL-CREATETABLE-STORAGE-PARAMETERS)をテーブルレベルで設定できます。これは、データベース全体の動作を変更するより適切である場合があります。大きなテーブルでは、極端な設定にする必要が生じる場合がありますが、autovacuum がすべてのテーブルに対してそのように動作するわけではありません。

次のクエリは、現在テーブルレベルのオプションが設定されているテーブルを表示します。

```
SELECT relname, reloptions
FROM pg_class
WHERE reloptions IS NOT null;
```

これが役立つ可能性がある例として、残りのテーブルよりかなり大きいテーブルがあります。1 個の 300 GB のテーブルと、他の 30 個の 1 GB 未満のテーブルがあるとします。この場合、システム全体の動作を変更しないで、大きなテーブルのいくつかの特定のパラメータを設定できます。

```
ALTER TABLE mytable set (autovacuum_vacuum_cost_delay=0);
```

これを行うと、このテーブルでコストベースの自動バキューム遅延がなくなりますが、システムでのリソース使用量が多くなります。通常、自動バキュームは `autovacuum_cost_limit` に達するたびに `autovacuum_vacuum_cost_delay` で一時停止します。詳細については、「PostgreSQL ドキュメント」の「[cost-based vacuuming](https://www.postgresql.org/docs/current/static/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-VACUUM-COST)」(コストベースのバキューム処理) を参照してください。

# 自動バキュームおよびバキュームアクティビティのログ記録
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum.Logging"></a>

自動バキュームアクティビティに関する情報は、`rds.force_autovacuum_logging_level`パラメータで指定したレベルに基づいて `postgresql.log` に送信されます。このパラメータで指定できる値、およびその値がデフォルトで設定されている PostgreSQL バージョンは次のとおりです。
+ `disabled` (PostgreSQL 10、PostgreSQL 9.6)
+ `debug5`, `debug4`, `debug3`, `debug2`, `debug1`
+ `info` (PostgreSQL 12、PostgreSQL 11)
+ `notice`
+ `warning` (PostgreSQL 13 以降)
+ `error`、ログ、`fatal`、`panic`

`rds.force_autovacuum_logging_level` では `log_autovacuum_min_duration` パラメータが使用されます。`log_autovacuum_min_duration` パラメータの値はしきい値 (ミリ秒単位) です。このしきい値を超過すると、自動バキュームアクションがログに記録されます。`-1` に設定するとログに何も記録されませんが、0 に設定するとすべてのアクションが記録されます。`rds.force_autovacuum_logging_level` と同様に、`log_autovacuum_min_duration` のデフォルト値はバージョンによって次のように異なります。
+ `10000 ms` – PostgreSQL 14、PostgreSQL 13、PostgreSQL 12、および PostgreSQL 11 
+ `(empty)` – PostgreSQL 10 と PostgreSQL 9.6 の場合、デフォルト値はありません

`rds.force_autovacuum_logging_level` を `WARNING` に設定することをお勧めします。`log_autovacuum_min_duration` についても 1,000～5,000 の値に設定することをお勧めします。5,000 に設定すると、5,000 ミリ秒を超える長さのアクティビティがログに記録されます。-1 以外の設定では、ロックの競合または同時に削除されたリレーションが原因で自動バキュームアクションがスキップされた場合にも、メッセージがログに記録されます。詳細については、「PostgreSQL のドキュメント」の「[Automatic Vacuuming](https://www.postgresql.org/docs/current/runtime-config-autovacuum.html)」(自動バキューム処理) を参照してください。

問題のトラブルシューティングを行うために、`rds.force_autovacuum_logging_level` パラメータを `debug1` から `debug5` までのデバッグレベルの 1 つに変更し、最も詳しい情報を取得します。デバッグ設定は、短期間かつトラブルシューティングの目的でのみ使用することをお勧めします。詳細については、「PostgreSQL のドキュメント」の「[When to log](https://www.postgresql.org/docs/current/static/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-WHEN)」(ログ記録のタイミング) を参照してください。

**注記**  
PostgreSQL では、`rds_superuser` アカウントが `pg_stat_activity` 内の autovacuum セッションを表示できます。例えば、コマンドの実行をブロックしている autovacuum セッション、あるいは手動で発行される vacuum コマンドよりも実行スピードが遅い autovacuum セッションを特定して終了することもできます。

# 無効なデータベースでの自動バキュームの動作を理解する
<a name="appendix.postgresql.commondbatasks.autovacuumbehavior"></a>

 新しい値 `-2` が `pg_database` カタログの `datconnlimit` 列に導入され、DROP DATABASE 操作の途中で中断されたデータベースが無効であることが示されます。

 この新しい値は、次の RDS for PostgreSQL バージョンで使用できます。
+ 15.4 以降のすべてのバージョン
+ 14.9 以降のバージョン
+ 13.12 以降のバージョン
+ 12.16 以降のバージョン
+ 11.21 以降のバージョン

無効なデータベースは、有効なデータベースに対する自動バキュームのフリーズ機能には影響しません。自動バキュームは無効なデータベースを無視します。そのため、通常のバキューム操作は、PostgreSQL 環境内のすべての有効なデータベースに対して正常かつ効率的に機能し続けます。

**Topics**
+ [トランザクション ID のモニタリング](#appendix.postgresql.commondbatasks.autovacuum.monitorxid)
+ [モニタリングクエリの調整](#appendix.postgresql.commondbatasks.autovacuum.monitoradjust)
+ [無効なデータベースの問題の解決](#appendix.postgresql.commondbatasks.autovacuum.connissue)

## トランザクション ID のモニタリング
<a name="appendix.postgresql.commondbatasks.autovacuum.monitorxid"></a>

 `age(datfrozenxid)` 関数は、通常、トランザクション ID のラップアラウンドを防ぐため、データベースのトランザクション ID (XID) の経過時間をモニタリングするために使用されます。

 無効なデータベースは自動バキュームから除外されるため、そのトランザクション ID (XID) カウンターは最大値 `2 billion` に達すると、`- 2 billion` にラップアラウンドして、このサイクルを無限に続けることができます。トランザクション ID のラップアラウンドをモニタリングする一般的なクエリは次のようになります。

```
SELECT max(age(datfrozenxid)) FROM pg_database;
```

ただし、`datconnlimit` に -2 値を導入した場合、無効なデータベースによってこのクエリの結果が歪む可能性があります。これらのデータベースは有効ではなく、定期的なメンテナンスチェックの一部に含めるべきではないため、誤検出が発生し、`age(datfrozenxid)` が実際よりも大きいという誤解を招く可能性があります。

## モニタリングクエリの調整
<a name="appendix.postgresql.commondbatasks.autovacuum.monitoradjust"></a>

 正確なモニタリングを行うには、モニタリングクエリを調整して無効なデータベースを除外する必要があります。次の推奨クエリに従ってください。

```
SELECT
    max(age(datfrozenxid))
FROM
    pg_database
WHERE
    datconnlimit <> -2;
```

このクエリにより、有効なデータベースのみが `age(datfrozenxid)` 計算で考慮され、PostgreSQL 環境全体のトランザクション ID の経過時間が正確に反映されます。

## 無効なデータベースの問題の解決
<a name="appendix.postgresql.commondbatasks.autovacuum.connissue"></a>

 無効なデータベースに接続しようとすると、次のようなエラーメッセージが表示されることがあります。

```
postgres=> \c db1
connection to server at "mydb.xxxxxxxxxx.us-west-2.rds.amazonaws.com" (xx.xx.xx.xxx), port xxxx failed: FATAL:  cannot connect to invalid database "db1"
HINT:  Use DROP DATABASE to drop invalid databases.
Previous connection kept
```

 さらに、`log_min_messages` パラメータが `DEBUG2` 以上に設定されている場合、自動バキュームプロセスが無効なデータベースをスキップしていることを示す次のログエントリが表示されることがあります。

```
       
2024-07-30 05:59:00 UTC::@:[32000]:DEBUG:  autovacuum: skipping invalid database "db6"
2024-07-30 05:59:00 UTC::@:[32000]:DEBUG:  autovacuum: skipping invalid database "db1"
```

この問題を解決するには、接続の試行中に提供される `HINT` に従ってください。RDS マスターアカウントまたは `rds_superuser` ロールを持つデータベースアカウントを使用して有効なデータベースに接続し、無効なデータベースを削除します。

```
SELECT
    'DROP DATABASE ' || quote_ident(datname) || ';'
FROM
    pg_database
WHERE
    datconnlimit = -2 \gexec
```

# RDS for PostgreSQL で積極的なバキュームのブロック要因を特定して解決する
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring"></a>

PostgreSQL でデータベースの正常な状態を維持するためにはバキューム処理が不可欠です。バキューム処理によって、ストレージの再利用が可能になり、[トランザクション ID の循環](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)に関する問題を回避できます。しかし、バキューム処理が目的どおりに動作しなくなることもあります。これにより、パフォーマンスの低下やストレージの肥大化が生じ、トランザクション ID の循環によって DB インスタンスの可用性にも影響する場合があります。したがって、データベースのパフォーマンスと可用性を最適化するには、これらの問題を特定して解決することが不可欠です。「[Understanding autovacuum in Amazon RDS for PostgreSQL environments](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/)」で自動バキュームの詳細について確認してください。

`postgres_get_av_diag()` 関数は、積極的なバキュームの進行を妨げたり遅らせたりしている問題を特定するのに役立ちます。推奨事項が提示され、問題が特定可能な場合はそれを解決するためのコマンドが、問題を特定できない場合は詳細な診断のためのガイダンスが得られます。積極的なバキュームのブロック要因は、経過時間が RDS の[適応型自動バキューム](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming)のしきい値である 5 億トランザクション ID を超えた場合に報告されます。

**トランザクション ID の経過時間とは**

トランザクション ID の `age()` 関数は、データベース (`pg_database.datfrozenxid`) またはテーブル (`pg_class.relfrozenxid`) の最も古いフリーズしていないトランザクション ID 以降に発生したトランザクションの数を計算します。この値は、前回の積極的なバキューム操作以降のデータベースアクティビティを示し、今後の VACUUM プロセスのワークロードについての見通しを示します。

**積極的なバキュームとは**

積極的な VACUUM 操作では、通常の VACUUM で省略されるページも含め、テーブル内のすべてのページが包括的にスキャンされます。この徹底的なスキャンは、最大経過時間に近づいているトランザクション ID を「フリーズ」することを目指しており、[トランザクション ID の循環](https://www.postgresql.org/docs/current/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND)と呼ばれる状況を効果的に防止します。

`postgres_get_av_diag()` で報告されるブロック要因は、5 億トランザクション以上古いものとなります。

**Topics**
+ [RDS for PostgreSQL に自動バキュームのモニタリングツールと診断ツールをインストールする](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation.md)
+ [RDS for PostgreSQL の postgres\$1get\$1av\$1diag() の関数](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions.md)
+ [RDS for PostgreSQL での識別可能なバキュームブロック要因の解決](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md)
+ [RDS for PostgreSQL での識別不能なバキュームブロック要因の解決](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers.md)
+ [RDS for PostgreSQL でバキュームのパフォーマンスに関する問題を解決する](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance.md)
+ [RDS for PostgreSQL の NOTICE メッセージの説明](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)

# RDS for PostgreSQL に自動バキュームのモニタリングツールと診断ツールをインストールする
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation"></a>

`postgres_get_av_diag()` 関数は現在、次の RDS for PostgreSQL バージョンで使用できます。
+ 17.2 以降の 17 バージョン
+ 16.7 以降の 16 バージョン
+ 15.11 以降の 15 バージョン
+ 14.16 以降の 14 バージョン
+ 13.19 以降の 13 バージョン

 `postgres_get_av_diag()` を使用するには、`rds_tools` 拡張機能を作成します。

```
postgres=> CREATE EXTENSION rds_tools ;
CREATE EXTENSION
```

拡張機能がインストールされていることを確認します。

```
postgres=> \dx rds_tools
             List of installed extensions
   Name    | Version |  Schema   |                    Description
 ----------+---------+-----------+----------------------------------------------------------
 rds_tools |   1.8   | rds_tools | miscellaneous administrative functions for RDS PostgreSQL
 1 row
```

関数が作成されていることを確認します。

```
postgres=> SELECT
    proname function_name,
    pronamespace::regnamespace function_schema,
    proowner::regrole function_owner
FROM
    pg_proc
WHERE
    proname = 'postgres_get_av_diag';
    function_name     | function_schema | function_owner
----------------------+-----------------+----------------
 postgres_get_av_diag | rds_tools       | rds_superuser
(1 row)
```

# RDS for PostgreSQL の postgres\$1get\$1av\$1diag() の関数
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions"></a>

`postgres_get_av_diag()` 関数は、RDS for PostgreSQL データベースで妨害または遅延が生じている自動バキュームプロセスに関する診断情報を取得します。正確な結果を得るには、最も古いトランザクション ID を持つデータベースでクエリを実行する必要があります。最も古いトランザクション ID を持つデータベースを使用する方法の詳細については、「[トランザクション ID の経過時間が最も古いデータベースに接続していない](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)」を参照してください。

```
SELECT
    blocker,
    DATABASE,
    blocker_identifier,
    wait_event,
    TO_CHAR(autovacuum_lagging_by, 'FM9,999,999,999') AS autovacuum_lagging_by,
    suggestion,
    suggested_action
FROM (
    SELECT
        *
    FROM
        rds_tools.postgres_get_av_diag ()
    ORDER BY
        autovacuum_lagging_by DESC) q;
```

`postgres_get_av_diag()` 関数は次の情報を含むテーブルを返します。

**blocker**  
バキュームをブロックしているデータベースアクティビティのカテゴリを指定します。  
+ [アクティブなステートメント](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement)
+ [トランザクションでのアイドル状態](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction)
+ [準備済みトランザクション](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction)
+ [論理レプリケーションスロット](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot)
+ [物理レプリケーションスロットを使用するリードレプリカ](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [ストリーミングレプリケーションを使用するリードレプリカ](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [一時テーブル](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables)

**database**  
該当しサポートされている場合にデータベースの名前を指定します。これは、アクティビティが進行中で、自動バキュームをブロックしている、またはこれからブロックするデータベースです。これは、接続してアクションを実行する必要があるデータベースです。

**blocker\$1identifier**  
自動バキュームをブロックしている、またはこれからブロックするアクティビティの識別子を指定します。識別子は、プロセス ID に SQL ステートメント、準備済みトランザクション、リードレプリカの IP アドレス、および論理または物理レプリケーションスロットの名前を加えたものとなります。

**wait\$1event**  
ブロックしているセッションの[待機イベント](PostgreSQL.Tuning.md)を指定し、次のブロック要因に適用されます。  
+ アクティブなステートメント
+ トランザクションでのアイドル状態

**autovacum\$1lagging\$1by**  
バックログ作業で自動バキュームが停滞しているトランザクションの数をカテゴリごとに指定します。

**suggestion**  
ブロック要因を解決するための推奨事項を指定します。これらの手順には、アクティビティが存在するデータベースの名前 (該当する場合)、セッションのプロセス ID (PID)(該当する場合)、および実行するアクションが含まれます。

**suggested\$1action**  
ブロック要因を解決するために実行する必要があるアクションを提案します。

# RDS for PostgreSQL での識別可能なバキュームブロック要因の解決
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Identifiableblockers"></a>

自動バキュームは積極的なバキュームを実行し、トランザクション ID の経過時間が RDS インスタンスの `autovacuum_freeze_max_age` パラメータで指定されたしきい値に達しないようにします。この経過時間は、Amazon CloudWatch メトリクス `MaximumUsedTransactionIDs` を使用して追跡できます。

Amazon RDS インスタンスの `autovacuum_freeze_max_age` の設定 (デフォルトは 2 億トランザクション ID) を確認するには、次のクエリを使用します。

```
SELECT
    TO_CHAR(setting::bigint, 'FM9,999,999,999') autovacuum_freeze_max_age
FROM
    pg_settings
WHERE
    name = 'autovacuum_freeze_max_age';
```

`postgres_get_av_diag()` では、経過時間が Amazon RDS の[適応型自動バキューム](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum.AdaptiveAutoVacuuming)のしきい値である 5 億トランザクション ID を超えた場合にのみ、積極的なバキュームのブロック要因をチェックすることに注意してください。`postgres_get_av_diag()` で検出されるブロック要因は、5 億トランザクション以上古いものとなります。

`postgres_get_av_diag()` 関数は、次のタイプのブロック要因を識別します。

**Topics**
+ [アクティブなステートメント](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement)
+ [トランザクションでのアイドル状態](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction)
+ [準備済みトランザクション](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction)
+ [論理レプリケーションスロット](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot)
+ [リードレプリカ](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas)
+ [一時テーブル](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables)

## アクティブなステートメント
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Active_statement"></a>

PostgreSQL において、アクティブなステートメントとは、データベースによって現在実行されている SQL ステートメントです。これには、クエリ、トランザクション、または進行中のすべてのオペレーションが含まれます。`pg_stat_activity` を使ってモニタリングする場合、状態列には、対応する PID を持つプロセスがアクティブであることが示されます。

`postgres_get_av_diag()` 関数がアクティブなステートメントであるステートメントを識別すると、次のような出力を表示します。

```
blocker               | Active statement
database              | my_database
blocker_identifier    | SELECT pg_sleep(20000);
wait_event            | Timeout:PgSleep
autovacuum_lagging_by | 568,600,871
suggestion            | Connect to database "my_database", review carefully and you may consider terminating the process using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_terminate_backend (29621);"}
```

**推奨されるアクション**

`suggestion` 列のガイダンスに従って、ユーザーはアクティブなステートメントが存在するデータベースに接続できます。`suggested_action` 列で指定されているように、セッションを終了するオプションを慎重に検討することが推奨されます。終了しても安全な場合は、`pg_terminate_backend()` 関数を使用してセッションを終了できます。このアクションは、管理者 (RDS マスターアカウントなど) または必要な `pg_terminate_backend()` 権限を持つユーザーが実行できます。

**警告**  
終了したセッションは、行われた変更を元に戻します (`ROLLBACK`)。要件に応じて、ステートメントを再度実行できます。ただし、自動バキュームプロセスが積極的なバキューム操作を完了した後にのみ実行することをお勧めします。

## トランザクションでのアイドル状態
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Idle_in_transaction"></a>

トランザクションステートメントのアイドル状態とは、明示的なトランザクションを開き (`BEGIN` ステートメントの発行など)、何らかの作業を実行したセッションで、クライアントがさらに作業を渡すか、`COMMIT`、`ROLLBACK`、`END` (暗黙的な `COMMIT` になります) を発行してトランザクションの終了を通知するのを待っているセッションを指します。

`postgres_get_av_diag()` 関数が `idle in transaction` ステートメントをブロック要因として識別すると、次のような出力を表示します。

```
blocker               | idle in transaction
database              | my_database
blocker_identifier    | INSERT INTO tt SELECT * FROM tt;
wait_event            | Client:ClientRead
autovacuum_lagging_by | 1,237,201,759
suggestion            | Connect to database "my_database", review carefully and you may consider terminating the process using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_terminate_backend (28438);"}
```

**推奨されるアクション**

`suggestion` 列に示されているように、トランザクションセッションでのアイドル状態が存在するデータベースに接続し、`pg_terminate_backend()` 関数を使用してセッションを終了できます。ユーザーは、管理者 (RDS マスターアカウント) ユーザーでも、 `pg_terminate_backend()` 権限を持つユーザーでもかまいません。

**警告**  
終了したセッションは、行われた変更を元に戻します (`ROLLBACK`)。要件に応じて、ステートメントを再度実行できます。ただし、自動バキュームプロセスが積極的なバキューム操作を完了した後にのみ実行することをお勧めします。

## 準備済みトランザクション
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Prepared_transaction"></a>

PostgreSQL では、[準備済みトランザクション](https://www.postgresql.org/docs/current/sql-prepare-transaction.html)と呼ばれる 2 相コミット戦略の一部であるトランザクションを使用できます。これらは、`max_prepared_transactions` パラメータをゼロ以外の値に設定することで有効になります。準備済みトランザクションは、データベースのクラッシュ、再起動、またはクライアントの切断後も、トランザクションが持続し、引き続き使用できるように設計されています。通常のトランザクションと同様に、トランザクション ID が割り当てられ、自動バキュームに影響を与える場合があります。準備状態のままにすると、自動バキュームはフリーズを実行できず、トランザクション ID の循環につながる可能性があります。

トランザクションマネージャによって解決されることなく無期限に準備状態となったトランザクションは、孤立した準備済みトランザクションになります。これを修正する唯一の方法は、`COMMIT PREPARED` コマンドまたは `ROLLBACK PREPARED` コマンドを使用してトランザクションをコミットするかロールバックすることです。

**注記**  
準備済みトランザクションで作成されたバックアップには、復元後もそのトランザクションが含まれることに注意してください。このようなトランザクションを見つけて閉じる方法については、以下の情報を参照してください。

`postgres_get_av_diag()` 関数が準備済みトランザクションをブロック要因として識別すると、次の出力を表示します。

```
blocker               | Prepared transaction
database              | my_database
blocker_identifier    | myptx
wait_event            | Not applicable
autovacuum_lagging_by | 1,805,802,632
suggestion            | Connect to database "my_database" and consider either COMMIT or ROLLBACK the prepared transaction using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"COMMIT PREPARED 'myptx';",[OR],"ROLLBACK PREPARED 'myptx';"}
```

**推奨されるアクション**

suggestion 列で説明されているように、準備済みトランザクションがあるデータベースに接続します。`suggested_action` 列に基づいて、`COMMIT` と `ROLLBACK` のどちらを実行するかを慎重に検討し、適切なアクションを選択します。

準備済みトランザクション全般をモニタリングするために、PostgreSQL には `pg_prepared_xacts` というカタログビューが用意されています。次のクエリを使用して、準備済みトランザクションを検索できます。

```
SELECT
    gid,
    prepared,
    owner,
    database,
    transaction AS oldest_xmin
FROM
    pg_prepared_xacts
ORDER BY
    age(transaction) DESC;
```

## 論理レプリケーションスロット
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Logical_replication_slot"></a>

レプリケーションスロットの目的は、ターゲットサーバーにレプリケートされるまで、未使用の変更を保持することです。詳細については、PostgreSQL の「[Logical replication](https://www.postgresql.org/docs/current/logical-replication.html)」を参照してください。

論理レプリケーションスロットには 2 つのタイプがあります。

**非アクティブな論理レプリケーションスロット**

レプリケーションが終了すると、未使用のトランザクションログは削除されず、レプリケーションスロットは非アクティブになります。非アクティブな論理レプリケーションスロットは、現在、サブスクライバーによって使用されていませんが、サーバーには残るため、WAL ファイルが保持され、古いトランザクションログが削除されなくなります。システムは LSN 情報が上書きされないよう保持する必要があるため、ディスク使用量が増加し、具体的には、自動バキュームで内部カタログテーブルをクリーンアップできなくなる可能性があります。放置するとカタログの肥大化とパフォーマンスの低下を招き、循環バキュームのリスクが増大して、トランザクションのダウンタイムが発生する可能性があります。

**アクティブだが遅い論理レプリケーションスロット**

論理レプリケーションのパフォーマンスの低下により、カタログのデッドタプルの削除が遅れることがあります。このレプリケーションの遅延により、`catalog_xmin` の更新が遅れ、カタログの肥大化や循環バキュームが発生する可能性があります。

`postgres_get_av_diag()` 関数が論理レプリケーションスロットをブロック要因として検出すると、次のような出力を表示します。

```
blocker               | Logical replication slot
database              | my_database
blocker_identifier    | slot1
wait_event            | Not applicable
autovacuum_lagging_by | 1,940,103,068
suggestion            | Ensure replication is active and resolve any lag for the slot if active. If inactive, consider dropping it using the command in suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"SELECT pg_drop_replication_slot('slot1') FROM pg_replication_slots WHERE active = 'f';"}
```

**推奨されるアクション**

この問題を解決するには、レプリケーション設定で、適用プロセスを終了している可能性のあるターゲットスキーマまたはデータの問題を確認します。最も一般的な理由を次に示します。
+ 列の欠落
+ 互換性のないデータ型
+ データの不一致
+ データの欠落

問題がインフラストラクチャの問題に関連している場合
+ ネットワークの問題 - [互換性のないネットワーク状態にある Amazon RDS DB の問題を解決するにはどうすればよいですか?](https://repost.aws/knowledge-center/rds-incompatible-network)
+ データベースまたは DB インスタンスが、次の理由により使用できない
  + レプリカインスタンスのストレージが不足している - 「[Amazon RDS DB インスタンスのストレージが不足したときに発生する問題を解決する方法を教えてください](https://repost.aws/knowledge-center/rds-out-of-storage)」を参照して、ストレージの追加について確認してください。
  + 互換性のないパラメータ - 「[互換性のないパラメータステータスのままになっている Amazon RDS DB インスタンスを修正するにはどうすればよいですか?](https://repost.aws/knowledge-center/rds-incompatible-parameters)」を参照して、問題を解決する方法の詳細を確認してください。

インスタンスが AWS ネットワーク外または AWS EC2 上にある場合は、可用性またはインフラストラクチャ関連の問題の解決方法について管理者に問い合わせてください。

**非アクティブなスロットの削除**

**警告**  
注意: レプリケーションスロットを削除する前に、レプリケーションが進行中ではないこと、レプリケーションスロットが非アクティブで回復不可能な状態であることを慎重に確認してください。スロットを途中で削除すると、レプリケーションが中断されたり、データが失われたりする可能性があります。

レプリケーションスロットが不要になったことを確認したら、削除して自動バキュームを続行できるようにします。条件 `active = 'f'` を指定することで、非アクティブなスロットのみが削除されます。

```
SELECT pg_drop_replication_slot('slot1') WHERE active ='f'
```

## リードレプリカ
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Read_replicas"></a>

[Amazon RDS リードレプリカ](USER_PostgreSQL.Replication.ReadReplicas.md)で `hot_standby_feedback` 設定が有効になっている場合、リードレプリカで実行されているクエリで引き続き必要になる可能性のあるデッド行は、プライマリデータベースの自動バキュームで削除されません。これは、レプリケーションスロットを使用して管理されているかどうかにかかわらず、すべてのタイプの物理リードレプリカに影響します。スタンバイレプリカで実行されているクエリでは、[クエリの競合](https://www.postgresql.org/docs/current/hot-standby.html#HOT-STANDBY-CONFLICT)やキャンセルを防ぐために、これらの行をプライマリで利用できる状態に保つ必要があるため、こうした動作が必要になります。

**物理レプリケーションスロットを使用するリードレプリカ**  
物理レプリケーションスロットを使用するリードレプリカでは、RDS for PostgreSQL でのレプリケーションの信頼性と安定性が大幅に強化されます。これらのスロットにより、プライマリデータベースはレプリカが処理するまで重要なログ先行書き込みファイルを保持し、ネットワークの中断中もデータ整合性を維持できます。

RDS for PostgreSQL バージョン 14 以降、すべてのレプリカでレプリケーションスロットが使用されます。以前のバージョンでは、クロスリージョンレプリカのみでレプリケーションスロットが使用されていました。

`postgres_get_av_diag()` 関数が物理レプリケーションスロットを使用するリードレプリカをブロック要因として検出すると、次のような出力を表示します。

```
blocker               | Read replica with physical replication slot
database              |
blocker_identifier    | rds_us_west_2_db_xxxxxxxxxxxxxxxxxxxxx
wait_event            | Not applicable
autovacuum_lagging_by | 554,080,689
suggestion            | Run the following query on the replica "rds_us_west_2_db_xxxxxxxxxxxxxxxxxxxx" to find the long running query:                           
                      | SELECT * FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 757989377;                                                       
                      | Review carefully and you may consdier terminating the query on read replica using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.                                 +                      |
suggested_action      | {"SELECT pg_terminate_backend(pid) FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 757989377;","                                                                                 +
                      | [OR]                                                                                                                                                                                                 +
                      | ","Disable hot_standby_feedback","                                                                                                                                                                   +
                      | [OR]                                                                                                                                                                                                 +
                      | ","Delete the read replica if not needed"}
```

**ストリーミングレプリケーションを使用するリードレプリカ**  
Amazon RDS では、バージョン 13 までの古いバージョンで、物理レプリケーションスロットを使用せずにリードレプリカを設定できます。このアプローチでは、プライマリが WAL ファイルをより積極的にリサイクルできるようにすることでオーバーヘッドを軽減します。これは、ディスク容量が制限された環境においてメリットがあり、ときどき発生するレプリケーションの遅延も許容できます。ただし、スロットを使用しない場合、WAL ファイルが欠落しないように、スタンバイは同期したままにする必要があります。Amazon RDS は、レプリカが遅れをとった場合にアーカイブされた WAL ファイルを使用して遅れを解消しますが、このプロセスには慎重なモニタリングが必要となり、時間がかかることがあります。

`postgres_get_av_diag()` 関数がストリーミングリードレプリカをブロック要因として検出すると、次のような出力を表示します。

```
blocker               | Read replica with streaming replication slot
database              | Not applicable
blocker_identifier    | xx.x.x.xxx/xx
wait_event            | Not applicable
autovacuum_lagging_by | 610,146,760
suggestion            | Run the following query on the replica "xx.x.x.xxx" to find the long running query:                                                                                                                                                         +
                      | SELECT * FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 348319343;                                                                                                                                                     +
                      | Review carefully and you may consdier terminating the query on read replica using suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.                                       +
                      |
suggested_action      | {"SELECT pg_terminate_backend(pid) FROM pg_catalog.pg_stat_activity WHERE backend_xmin::text::bigint = 348319343;","                                                                                                                        +
                      | [OR]                                                                                                                                                                                                                                        +
                      | ","Disable hot_standby_feedback","                                                                                                                                                                                                          +
                      | [OR]                                                                                                                                                                                                                                        +
                      | ","Delete the read replica if not needed"}
```

**推奨されるアクション**

`suggested_action` 列で推奨されているように、以下のオプションを慎重に検討して自動バキュームのブロックを解除します。
+ **クエリを終了する** – suggestion 列のガイダンスに従って、suggested\$1action 列で指定されているようにリードレプリカに接続できます。セッションを終了するオプションは慎重に検討することをお勧めします。終了しても安全であると判断した場合は、`pg_terminate_backend()` 関数を使用してセッションを終了できます。このアクションは、管理者 (RDS マスターアカウントなど) または必要な pg\$1terminate\$1backend() 権限を持つユーザーが実行できます。

  リードレプリカで次の SQL コマンドを実行すると、プライマリのバキュームによる古い行のクリーンアップを妨げているクエリを終了できます。`backend_xmin` の値は、関数の出力で報告されます。

  ```
  SELECT
      pg_terminate_backend(pid)
  FROM
      pg_catalog.pg_stat_activity
  WHERE
      backend_xmin::text::bigint = backend_xmin;
  ```
+ **ホットスタンバイフィードバックを無効にする** – `hot_standby_feedback` パラメータがバキュームの大幅な遅延の原因となっている場合は、これを無効にすることを検討します。

  `hot_standby_feedback` パラメータを使用すると、リードレプリカはクエリアクティビティについてプライマリに通知し、プライマリがスタンバイで使用されているテーブルや行をバキューム処理できないようにします。これによりスタンバイでのクエリの安定性が確保されますが、プライマリでのバキューム処理が大幅に遅延する可能性があります。この機能を無効にすると、プライマリはスタンバイが追いつくのを待たずにバキューム処理を進めることができます。ただし、プライマリによってバキューム処理された行にアクセスしようとすると、スタンバイでクエリのキャンセルや失敗が発生する可能性があります。
+ **不要になったリードレプリカを削除する** – リードレプリカが不要になった場合は、削除できます。これにより、関連するレプリケーションオーバーヘッドが解消され、プライマリがレプリカによって妨げられることなくトランザクションログをリサイクルできるようになります。

## 一時テーブル
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Temporary_tables"></a>

`TEMPORARY` キーワードを使用して作成された[一時テーブル](https://www.postgresql.org/docs/current/sql-createtable.html)は、pg\$1temp\$1xxx などの一時スキーマにあり、それらを作成したセッションのみがアクセスできます。一時テーブルは、セッションが終了すると削除されます。ただし、このようなテーブルは PostgreSQL の自動バキュームプロセスには表示されず、テーブルを作成したセッションによって手動でバキューム処理する必要があります。別のセッションから一時テーブルのバキューム処理を試みても効果はありません。

異常な状況下では、テーブルを所有するアクティブなセッションがない状態で一時テーブルが存在します。致命的なクラッシュ、ネットワークの問題、または同様のイベントが原因でテーブルを所有するセッションが予期せず終了した場合、一時テーブルはクリーンアップされず、「孤立した」テーブルとして残される可能性があります。PostgreSQL 自動バキュームプロセスで孤立した一時テーブルが検出されると、次のメッセージがログに記録されます。

```
LOG: autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\"
```

`postgres_get_av_diag()` 関数が一時テーブルをブロック要因として識別すると、次のような出力を表示します。この関数で一時テーブルに関連する出力を正しく表示するには、それらのテーブルが存在するのと同じデータベース内で関数を実行する必要があります。

```
blocker               | Temporary table
database              | my_database
blocker_identifier    | pg_temp_14.ttemp
wait_event            | Not applicable
autovacuum_lagging_by | 1,805,802,632
suggestion            | Connect to database "my_database". Review carefully, you may consider dropping temporary table using command in suggested_action. For more information, see Working with PostgreSQL autovacuum in the Amazon RDS User Guide.
suggested_action      | {"DROP TABLE ttemp;"}
```

**推奨されるアクション**

出力の `suggestion` 列に示されている手順に従って、自動バキュームの実行を妨げている一時テーブルを特定して削除します。次のコマンドを使用して、`postgres_get_av_diag()` で報告された一時テーブルを削除します。`postgres_get_av_diag()` 関数で提示された出力に基づいてテーブル名を置き換えます。

```
DROP TABLE my_temp_schema.my_temp_table;
```

次のクエリを使用して、一時テーブルを識別できます。

```
SELECT
    oid,
    relname,
    relnamespace::regnamespace,
    age(relfrozenxid)
FROM
    pg_class
WHERE
relpersistence = 't'
ORDER BY
    age(relfrozenxid) DESC;
```

# RDS for PostgreSQL での識別不能なバキュームブロック要因の解決
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Unidentifiable_blockers"></a>

このセクションでは、バキューム処理の進行を妨げる可能性のあるその他の理由について説明します。以下の問題は、現在、`postgres_get_av_diag()` 関数によって直接識別できません。

**Topics**
+ [無効なページ](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages)
+ [インデックスの不整合](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency)
+ [トランザクションレートが極めて高い](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate)

## 無効なページ
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages"></a>

無効なページエラーは、PostgreSQL がページへのアクセス中にページのチェックサムの不一致を検出した場合に発生します。コンテンツが読み取れないため、自動バキュームでタプルがフリーズされません。これにより、クリーンアッププロセスが実質的に停止します。次のエラーが PostgreSQL の ログに書き込まれます。

```
WARNING:  page verification failed, calculated checksum YYYYY but expected XXXX
ERROR:  invalid page in block ZZZZZ of relation base/XXXXX/XXXXX
CONTEXT:  automatic vacuum of table myschema.mytable
```

**オブジェクトタイプを判断する**

```
ERROR: invalid page in block 4305910 of relation base/16403/186752608 
WARNING: page verification failed, calculated checksum 50065 but expected 60033
```

エラーメッセージのパス `base/16403/186752608` は、次の情報を提供しています。
+ 「base」は PostgreSQL データディレクトリのディレクトリ名です。
+ 「16403」はデータベース OID であり、`pg_database` システムカタログで検索できます。
+ 「186752608」は `relfilenode` であり、`pg_class` システムカタログでスキーマとオブジェクト名を検索するために使用できます。

影響を受けるデータベースで次のクエリの出力をチェックすることで、オブジェクトタイプを判断できます。次のクエリは、oid: 186752608 のオブジェクト情報を取得します。OID を、発生したエラーに関連する OID に置き換えます。

```
SELECT
    relname AS object_name,
    relkind AS object_type,
    nspname AS schema_name
FROM
    pg_class c
    JOIN pg_namespace n ON c.relnamespace = n.oid
WHERE
    c.oid = 186752608;
```

詳細については、PostgreSQL のドキュメント「[https://www.postgresql.org/docs/current/catalog-pg-class.html](https://www.postgresql.org/docs/current/catalog-pg-class.html)」で、`pg_class` の `relkind` 列で示されるサポート対象のすべてのオブジェクトタイプを参照してください。

**ガイダンス**

この問題の最も効果的な解決策は、特定の Amazon RDS インスタンスの設定と、整合性のないページの影響を受けるデータの種類によって異なります。

**オブジェクトタイプがインデックスの場合**

インデックスを再構築することをお勧めします。
+ **`CONCURRENTLY` オプションの使用** – PostgreSQL バージョン 12 より前のバージョンでは、インデックスを再構築するには、排他的テーブルロックによってテーブルへのアクセスを制限する必要がありました。PostgreSQL バージョン 12 以降のバージョンでは、`CONCURRENTLY` オプションにより行レベルのロックが可能になり、テーブルの可用性が大幅に向上しています。コマンドは以下のとおりです。

  ```
  REINDEX INDEX ix_name CONCURRENTLY;
  ```

  `CONCURRENTLY` はそれほど破壊的ではありませんが、ビジー状態のテーブルでは時間がかかる場合があります。可能であれば、トラフィックが少ない時間帯にインデックスを構築することを検討してください。

  詳細については、PostgreSQL ドキュメントの「[REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)」を参照してください。
+ **`INDEX_CLEANUP FALSE` オプションの使用** – インデックスが大きく、完了までにかなりの時間がかかると予想される場合は、インデックスを除外しながら手動 `VACUUM FREEZE` を実行して自動バキュームのブロックを解除できます。この機能は PostgreSQL バージョン 12 以降で使用できます。

  インデックスを無視すると、整合性のないインデックスのバキュームプロセスを省略して、循環の問題を軽減できます。ただし、無効なページの根本的な問題は解決されません。無効なページの問題に完全に対処し、これを解決するには、インデックスを再構築する必要があります。

**オブジェクトタイプがマテリアライズドビューの場合**

マテリアライズドビューで無効なページエラーが発生した場合は、影響を受けるデータベースにログインし、更新して無効なページを解決します。

マテリアライズドビューを更新します。

```
REFRESH MATERIALIZED VIEW schema_name.materialized_view_name;
```

更新に失敗した場合は、再作成を試みます。

```
DROP MATERIALIZED VIEW schema_name.materialized_view_name;
CREATE MATERIALIZED VIEW schema_name.materialized_view_name AS query;
```

マテリアライズドビューを更新または再作成すると、基盤となるテーブルデータに影響を与えずにマテリアライズドビューが復元されます。

**他のすべてのオブジェクトタイプの場合**

他のすべてのオブジェクトタイプについては、AWS サポートに問い合わせてください。

## インデックスの不整合
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Index_inconsistency"></a>

論理的に整合性のないインデックスによって、自動バキュームの進行が妨げられる場合があります。次のエラーまたは同様のエラーは、インデックスのバキュームフェーズ中、または SQL ステートメントによってインデックスがアクセスされるときにログに記録されます。

```
ERROR: right sibling's left-link doesn't match:block 5 links to 10 instead of expected 2 in index ix_name
```

```
ERROR: failed to re-find parent key in index "XXXXXXXXXX" for deletion target page XXX
CONTEXT:  while vacuuming index index_name of relation schema.table
```

**ガイダンス**

手動 `VACUUM FREEZE` で `INDEX_CLEANUP` を使用してインデックスを再構築するか、インデックスを省略します。インデックスを再構築する方法の詳細については、「[オブジェクトタイプがインデックスの場合](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Invalid_pages)」を参照してください。
+ **CONCURRENTLY オプションの使用** – PostgreSQL バージョン 12 より前のバージョンでは、インデックスを再構築するには、排他的テーブルロックによってテーブルへのアクセスを制限する必要がありました。PostgreSQL バージョン 12 以降のバージョンでは、CONCURRENTLY オプションにより行レベルのロックが可能になり、テーブルの可用性が大幅に向上しています。コマンドは以下のとおりです。

  ```
  REINDEX INDEX ix_name CONCURRENTLY;
  ```

  CONCURRENTLY はそれほど破壊的ではありませんが、ビジー状態のテーブルでは時間がかかる場合があります。可能であれば、トラフィックが少ない時間帯にインデックスを構築することを検討してください。詳細については、*PostgreSQL* ドキュメントの「[REINDEX](https://www.postgresql.org/docs/current/sql-reindex.html)」を参照してください。
+ **INDEX\$1CLEANUP FALSE オプションの使用** – インデックスが大きく、完了までにかなりの時間がかかると予想される場合は、インデックスを除外しながら手動 VACUUM FREEZE を実行して自動バキュームのブロックを解除できます。この機能は PostgreSQL バージョン 12 以降で使用できます。

  インデックスを無視すると、整合性のないインデックスのバキュームプロセスを省略して、循環の問題を軽減できます。ただし、無効なページの根本的な問題は解決されません。無効なページの問題に完全に対処し、これを解決するには、インデックスを再構築する必要があります。

## トランザクションレートが極めて高い
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.High_transaction_rate"></a>

PostgreSQL では、トランザクションレートが高いと自動バキュームのパフォーマンスに大きな影響を与え、デッドタプルのクリーンアップが遅くなり、トランザクション ID の循環のリスクが高まります。トランザクションレートは、2 つの期間 (通常は 1 秒ごと) の `max(age(datfrozenxid))` の差を測定することでモニタリングできます。さらに、RDS Performance Insights の次のカウンターメトリクスを使用して、トランザクションの合計数であるトランザクションレート (xact\$1commit と xact\$1rollback の合計) を測定できます。


|  Counter  |  タイプ  |  単位  |  メトリクス  | 
| --- | --- | --- | --- | 
|  xact\$1commit  |  トランザクション  |  1 秒あたりのコミット数  |  db.Transactions.xact\$1commit  | 
|  xact\$1rollback  |  トランザクション  |  1 秒あたりのロールバック数  |  db.Transactions.xact\$1rollback  | 

急激な増加は、トランザクション負荷が高いことを示しており、自動バキュームが過負荷になり、肥大化、ロック競合、および潜在的なパフォーマンスの問題が発生する可能性があります。これにより、以下のような点で自動バキュームプロセスに悪影響が及ぶ可能性があります。
+ **テーブルアクティビティ:** バキューム処理されている特定のテーブルで大量のトランザクションが発生し、遅延が発生する可能性があります。
+ **システムリソース:** システム全体が過負荷になっている可能性があるため、自動バキュームが効率的に機能するために必要なリソースにアクセスすることが困難になります。

自動バキュームをより効果的に動作させ、遅延なくタスクに対処するために、次の戦略を検討してください。

1. 可能であれば、トランザクションレートを下げます。可能な場合は、類似したトランザクションをバッチ処理またはグループ化することを検討してください。

1. オフピークの時間帯は、毎晩、毎週、または隔週の手動 `VACUUM FREEZE` オペレーションで頻繁に更新されるテーブルをターゲットにします。

1. インスタンスクラスをスケールアップして、大量のトランザクションと自動バキュームを処理するためにより多くのシステムリソースを割り当てることを検討してください。

# RDS for PostgreSQL でバキュームのパフォーマンスに関する問題を解決する
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance"></a>

このセクションでは、バキュームのパフォーマンスの低下を招く要因と、それらの問題に対処する方法について説明します。

**Topics**
+ [大規模なインデックスのバキューム処理](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Large_indexes)
+ [バキューム処理対象のテーブルまたはデータベースが多すぎる](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Multiple_tables)
+ [(循環を防ぐための) 積極的なバキューム処理が実行されている](#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum)

## 大規模なインデックスのバキューム処理
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Large_indexes"></a>

VACUUM は、初期化、ヒープスキャン、インデックスとヒープバキューム、インデックスクリーンアップ、ヒープ切り捨て、最終クリーンアップのシーケンシャルフェーズで動作します。ヒープスキャン中、プロセスはページを除外し、デフラグしてフリーズします。ヒープスキャンが完了すると、VACUUM はインデックスをクリーンアップし、空のページがオペレーティングシステムに返されて、空き領域マップのバキューム処理や統計の更新などの最終的なクリーンアップタスクを実行します。

`maintenance_work_mem` (または `autovacuum_work_mem`) がインデックスの処理に不十分な場合は、インデックスのバキューム処理に複数のパスが必要になることがあります。PostgreSQL 16 以前では、デッドタプル ID を保存するために 1 GB のメモリ制限があり、大きなインデックスでは、多くの場合複数のパスが必要となっていました。PostgreSQL 17 では、単一の割り当て配列を使用する代わりにメモリを動的に割り当てる `TidStore` が導入されています。これにより、1 GB の制約がなくなり、メモリをより効率的に使用でき、インデックスごとに複数のインデックススキャンを行う必要が軽減されます。

使用可能なメモリがインデックス処理全体を一度に処理できない場合、大きなインデックスには PostgreSQL 17 で複数のパスが必要になることがあります。通常、大きなインデックスには、複数のパスを必要とするデッドタプルが多く含まれます。

**低速バキュームオペレーションの検出**

`postgres_get_av_diag()` 関数は、メモリ不足が原因でバキューム操作の実行が遅いタイミングを検出できます。この関数の詳細については、「[RDS for PostgreSQL に自動バキュームのモニタリングツールと診断ツールをインストールする](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Installation.md)」を参照してください。

この `postgres_get_av_diag()` 関数は、使用可能なメモリが 1 回のパスでインデックスのバキューム処理を完了するのに十分でない場合、次の通知を発行します。

**`rds_tools` 1.8**

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_work_mem is "XXX" and might not be sufficient. Consider increasing the setting, and if necessary, scaling up the Amazon RDS instance class for more memory. 
        Additionally, review the possibility of manual vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;).
```

**`rds_tools` 1.9**

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_work_mem is XX might not be sufficient. Consider increasing the setting to XXX, and if necessary, scaling up the RDS instance class for more 
        memory. The suggested value is an estimate based on the current number of dead tuples for the table being vacuumed, which might not fully reflect the latest state. Additionally, review the possibility of manual 
        vacuum with exclusion of indexes using (VACUUM (INDEX_CLEANUP FALSE, VERBOSE TRUE) table_name;). For more information, see 
        [Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html)
        .
```

**注記**  
`postgres_get_av_diag()` 関数では、`pg_stat_all_tables.n_dead_tup` を使用してインデックスのバキューム処理に必要なメモリ量を推定します。

`postgres_get_av_diag()` 関数が、`autovacuum_work_mem` が不十分なために複数のインデックススキャンを必要とするスローバキュームオペレーションを特定すると、次のメッセージが生成されます。

```
NOTICE: Your vacuum is performing multiple index scans due to insufficient autovacuum_work_mem:XXX for index vacuuming. 
        For more information, see [Working with PostgreSQL autovacuum in the Amazon Amazon RDS User Guide](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html).
```

**ガイダンス**

手動 `VACUUM FREEZE` を使用して次の回避策を適用し、テーブルのフリーズにかかる時間を短縮できます。

**バキューム処理のためのメモリを増やす**

`postgres_get_av_diag()` 関数で提案されているように、インスタンスレベルで潜在的なメモリの制約に対応するために、`autovacuum_work_mem` パラメータを増やすことをお勧めします。`autovacuum_work_mem` は動的パラメータですが、新しいメモリ設定を有効にするには、自動バキュームデーモンがワーカーを再起動する必要があることに注意してください。これを行うには、以下の手順を使用します。

1. 新しい設定が指定されていることを確認します。

1. 自動バキュームを現在実行しているプロセスを終了します。

このアプローチにより、調整されたメモリ割り当てが新しい自動バキューム操作に適用されます。

より迅速な結果を得るには、セッション内で `maintenance_work_mem` 設定を増やし、手動で `VACUUM FREEZE` 操作を実行することを検討してください。

```
SET maintenance_work_mem TO '1GB';
VACUUM FREEZE VERBOSE table_name;
```

Amazon RDS を使用していて、`maintenance_work_mem` または `autovacuum_work_mem` のより高い値をサポートするために追加のメモリが必要であると判断した場合は、より多くのメモリを持つインスタンスクラスにアップグレードすることを検討してください。これにより、手動バキューム操作と自動バキューム操作の両方を強化するために必要なリソースが提供され、バキューム処理とデータベースの全体的なパフォーマンスが向上します。

**INDEX\$1CLEANUP を無効にする**

PostgreSQL バージョン 12 以降の手動 `VACUUM` ではインデックスのクリーンアップフェーズを省略できますが、PostgreSQL バージョン 14 以降の緊急自動バキュームでは、[https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-VACUUM-FAILSAFE-AGE](https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-VACUUM-FAILSAFE-AGE) パラメータに基づいてこのフェーズが自動的に行われます。

**警告**  
インデックスのクリーンアップを省略すると、インデックスが肥大化し、クエリのパフォーマンスに悪影響を及ぼす可能性があります。これを軽減するには、メンテナンスウィンドウで、影響を受けるインデックスに対してインデックスの再作成またはバキューム処理を行うことを検討してください。

大きなインデックスの処理に関するその他のガイダンスについては、「[大きなインデックスを使った autovacuum の管理](Appendix.PostgreSQL.CommonDBATasks.Autovacuum.LargeIndexes.md)」のドキュメントを参照してください。

**インデックスの並列バキューム処理**

PostgreSQL 13 以降では、手動 `VACUUM` を使用して、各インデックスに 1 つのバキュームワーカープロセスを割り当て、デフォルトで複数のインデックスのバキューム処理とクリーンアップを並列して行うことができます。ただし、バキューム操作が並列実行の対象となるかどうかを PostgreSQL が判断するには、特定の基準を満たす必要があります。
+ 少なくとも 2 つのインデックスが必要です。
+ `max_parallel_maintenance_workers` パラメータを 2 以上に設定する必要があります。
+ インデックスサイズが `min_parallel_index_scan_size` の制限 (デフォルトは 512KB) を超えている必要があります。

Amazon RDS インスタンスで使用可能な vCPU の数とテーブルのインデックスの数に基づいて `max_parallel_maintenance_workers` 設定を調整し、バキューム処理のターンアラウンド時間を最適化できます。

詳細については、「[Parallel vacuuming in Amazon RDS for PostgreSQL and Amazon Aurora PostgreSQL](https://aws.amazon.com/blogs/database/parallel-vacuuming-in-amazon-rds-for-postgresql-and-amazon-aurora-postgresql/)」を参照してください。

## バキューム処理対象のテーブルまたはデータベースが多すぎる
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Multiple_tables"></a>

PostgreSQL の「[The Autovacuum Daemon](https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM')」ドキュメントで説明されているように、自動バキュームデーモンは複数のプロセスで動作します。このプロセスには、システム内の各データベースの自動バキュームワーカープロセスを開始する、永続的な自動バキュームランチャーが含まれます。ランチャーは、データベースあたり約 `autovacuum_naptime` 秒ごとにこれらのワーカーを開始するようにスケジュールします。

N 個のデータベースでは、新しいワーカーはおおよそ [`autovacuum_naptime`/N 秒] ごとに開始されます。ただし、同時ワーカーの合計数は `autovacuum_max_workers` 設定によって制限されます。バキューム処理を必要とするデータベースまたはテーブルの数がこの制限を超えると、ワーカーが利用可能になり次第すぐに次のデータベースまたはテーブルが処理されます。

多数の大きなテーブルやデータベースで同時にバキューム処理が必要な場合、使用可能なすべての自動バキュームワーカーが長時間占有され、他のテーブルやデータベースのメンテナンスに遅延が生じる可能性があります。トランザクションレートが高い環境では、このボトルネックがすぐに増大し、Amazon RDS インスタンス内で循環バキュームの問題が発生する可能性があります。

`postgres_get_av_diag()` が多数のテーブルまたはデータベースを検出すると、次の推奨事項が提示されます。

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound and it might be slow.
```

```
NOTICE: The current setting of autovacuum_max_workers:3 might not be sufficient. Consider increasing the setting and, if necessary, consider scaling up the Amazon RDS instance class for more workers.
```

**ガイダンス**

**autovacuum\$1max\$1workers を増やす**

バキューム処理を迅速化するために、`autovacuum_max_workers` パラメータを調整して同時実行の自動バキュームワーカーを増やすことをお勧めします。パフォーマンスのボトルネックが続く場合は、Amazon RDS インスタンスをより多くの vCPU を持つクラスにスケールアップすることを検討してください。これにより、並列処理機能をさらに向上させることができます。

## (循環を防ぐための) 積極的なバキューム処理が実行されている
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum"></a>

PostgreSQL のデータベースの経過時間 (MaximumUsedTransactionIDs) は、(循環を防ぐための) 積極的なバキューム処理が正常に完了した場合にのみ減少します。このバキューム処理が終了するまで、トランザクションレートに応じて経過時間は増加し続けます。

`postgres_get_av_diag()` 関数が積極的なバキュームを検出すると、次の `NOTICE` を生成します。ただし、この出力は、バキュームが少なくとも 2 分間アクティブになった後にのみトリガーされます。

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.
```

積極的なバキュームの詳細については、「[When an aggressive vacuum is already running](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE.md)」を参照してください。

次のクエリを使用して、積極的なバキュームが進行中かどうかを確認できます。

```
SELECT
    a.xact_start AS start_time,
    v.datname "database",
    a.query,
    a.wait_event,
    v.pid,
    v.phase,
    v.relid::regclass,
    pg_size_pretty(pg_relation_size(v.relid)) AS heap_size,
    (
        SELECT
            string_agg(pg_size_pretty(pg_relation_size(i.indexrelid)) || ':' || i.indexrelid::regclass || chr(10), ', ')
        FROM
            pg_index i
        WHERE
            i.indrelid = v.relid
    ) AS index_sizes,
    trunc(v.heap_blks_scanned * 100 / NULLIF(v.heap_blks_total, 0)) AS step1_scan_pct,
    v.index_vacuum_count || '/' || (
        SELECT
            count(*)
        FROM
            pg_index i
        WHERE
            i.indrelid = v.relid
    ) AS step2_vacuum_indexes,
    trunc(v.heap_blks_vacuumed * 100 / NULLIF(v.heap_blks_total, 0)) AS step3_vacuum_pct,
    age(CURRENT_TIMESTAMP, a.xact_start) AS total_time_spent_sofar
FROM
    pg_stat_activity a
    INNER JOIN pg_stat_progress_vacuum v ON v.pid = a.pid;
```

出力の query 列をチェックすることで、(循環を防ぐための) 積極的なバキュームであるかどうかを判断できます。「to prevent wraparound」という語句は、それが積極的なバキュームであることを示しています。

```
query                  | autovacuum: VACUUM public.t3 (to prevent wraparound)
```

例えば、トランザクション経過時間が 10 億の時点でブロック要因があり、同じトランザクション経過時間での循環を防ぐために積極的なバキューム処理を必要とするテーブルがあるとします。さらに、トランザクション経過時間が 7 億 5,000 万の時点で別のブロック要因もあります。トランザクション経過時間 10 億でのブロック要因をクリアしても、トランザクション経過時間はすぐに 7 億 5,000 万には低下しません。積極的なバキューム処理を必要とするテーブル、または経過時間が 7 億 5,000 万を超えるトランザクションが完了するまで、高いままとなります。この間、PostgreSQL クラスターのトランザクション経過時間は増加し続けます。バキューム処理が完了すると、トランザクションの経過時間は 7 億 5,000 万に低下しますが、さらにバキューム処理が完了するまで再び増加し始めます。このサイクルは、最終的にトランザクション経過時間が `autovacuum_freeze_max_age` で指定された Amazon RDS インスタンスの設定レベルに低下するまで、これらの条件が存続する限り続きます。

# RDS for PostgreSQL の NOTICE メッセージの説明
<a name="Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.NOTICE"></a>

 `postgres_get_av_diag()` 関数は、次の NOTICE メッセージを提供します。

**経過時間がまだモニタリングしきい値に達していない場合**  
ブロック要因を識別するための `postgres_get_av_diag()` のモニタリングしきい値は、デフォルトで 5 億トランザクションです。`postgres_get_av_diag()` で次の NOTICE が生成された場合は、トランザクション経過時間がまだこのしきい値に達していないことを示します。  

```
NOTICE: postgres_get_av_diag() checks for blockers that prevent aggressive vacuums only, it does so only after exceeding dvb_threshold which is 500,000,000 and age of this PostgreSQL cluster is currently at 2.
```

**トランザクション ID の経過時間が最も古いデータベースに接続していない**  
`postgres_get_av_diag()` 関数は、トランザクション ID の経過時間が最も古いデータベースに接続したときに、最も正確な出力を提供します。`postgres_get_av_diag()` によって報告されたトランザクション ID の経過時間が最も古いデータベースが、「my\$1database」とは異なる場合があります。正しいデータベースに接続していない場合、次の NOTICE が生成されます。  

```
NOTICE: You are not connected to the database with the age of oldest transaction ID. Connect to my_database database and run postgres_get_av_diag() for accurate reporting.
```
トランザクション経過時間が最も古いデータベースに接続することは、次の理由で重要です。  
+ **一時テーブルのブロック要因の識別:** 一時テーブルのメタデータは各データベースに固有のため、通常、一時テーブルは作成されたデータベースにあります。ただし、一時テーブルが上位のブロック要因となり、最も古いトランザクションを持つデータベースに存在する状況では、誤解が生じる可能性があります。適切なデータベースに接続することで、一時テーブルのブロック要因を正確に識別できます。
+ **遅いバキュームの診断:** インデックスメタデータとテーブル数の情報はデータベース固有であり、バキュームが遅い問題の診断に必要です。

**トランザクションの経過時間が最も古いデータベースが、rdsadmin または template0 データベースにある**  
場合によっては、`rdsadmin` または `template0` データベースが、トランザクション ID の経過時間が最も古いデータベースとして識別される場合があります。このような場合、`postgres_get_av_diag()` で次の NOTICE が発行されます。  

```
NOTICE: The database with the age of oldest transaction ID is rdsadmin or template0, reach out to support if the reported blocker is in rdsadmin or template0.
```
リストされたブロック要因がこれら 2 つのデータベースのいずれからも発生していないことを確認します。ブロック要因が `rdsadmin` または `template0` のいずれかに存在すると報告された場合は、サポートに問い合わせてください。ユーザーはこれらのデータベースにはアクセスできず、サポートが必要です。  
`rdsadmin` と `template0` データベースのいずれかに上位のブロック要因が含まれている可能性はほとんどありません。

**積極的なバキュームがすでに実行されている場合**  
`postgres_get_av_diag()` 関数は、積極的なバキューム処理が実行されているときに報告を行うように設計されていますが、この出力はバキュームが少なくとも 1 分間アクティブになった後にのみトリガーされます。この意図的な遅延によって、誤検出の可能性が低くなります。待機することで、有効で重要なバキュームのみが報告され、バキュームアクティビティのより正確で信頼性の高いモニタリングが可能になります。  
`postgres_get_av_diag()` 関数は、進行中の 1 つ以上の積極的なバキュームを検出すると、次の NOTICE を生成します。  

```
NOTICE: Your database is currently running aggressive vacuum to prevent wraparound, monitor autovacuum performance.
```
NOTICE に示されているように、バキュームのパフォーマンスを引き続きモニタリングします。積極的なバキュームの詳細については、「[(循環を防ぐための) 積極的なバキューム処理が実行されている](Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Resolving_Performance.md#Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Aggressive_vacuum)」を参照してください。

**自動バキュームがオフの場合**  
データベースインスタンスで自動バキュームが無効になっている場合、`postgres_get_av_diag()` 関数は次の NOTICE を生成します。  

```
NOTICE: Autovacuum is OFF, we strongly recommend to enable it, no restart is necessary.
```
自動バキュームは、RDS for PostgreSQL DB インスタンスの重要な機能であり、スムーズなデータベース操作を実現します。古い行バージョンを自動的に削除し、ストレージ領域を再利用して、テーブルの肥大化を防止することで、テーブルとインデックスの効率が維持され、パフォーマンスが最適化されます。さらに、Amazon RDS インスタンスのトランザクションを停止する可能性のある、トランザクション ID の循環も防止します。自動バキュームを無効にすると、データベースのパフォーマンスと安定性が長期的に低下する可能性があるため、常に有効にしておくことをお勧めします。詳細については、「[Understanding autovacuum in RDS for PostgreSQL environments](https://aws.amazon.com/blogs/database/understanding-autovacuum-in-amazon-rds-for-postgresql-environments/)」を参照してください。  
自動バキュームをオフにしても、積極的なバキュームは停止しません。積極的なバキュームは、テーブルが `autovacuum_freeze_max_age` しきい値に達すると実行されます。

**残っているトランザクションの数が非常に少ない**  
`postgres_get_av_diag()` 関数は、循環バキュームが差し迫った場合に次の NOTICE を生成します。この NOTICE は、Amazon RDS インスタンスが新しいトランザクションを拒否するまであと 1 億トランザクションに差し迫った場合に発行されます。  

```
WARNING: Number of transactions remaining is critically low, resolve issues with autovacuum or perform manual VACUUM FREEZE before your instance stops accepting transactions.
```
データベースのダウンタイムを回避するために、直ちにアクションが必要です。バキューム操作を注意深くモニタリングし、トランザクションの失敗を防ぐために、影響を受けるデータベースで `VACUUM FREEZE` を手動で開始することを検討する必要があります。