

# Amazon RDS for PostgreSQL での高いオブジェクト数の管理
<a name="PostgreSQL.HighObjectCount"></a>

PostgreSQL の制限は理論上のものですが、データベース内のオブジェクト数が非常に多いと、さまざまなオペレーションにおいてパフォーマンスに顕著な影響が及びます。このドキュメントでは、合計数が多い場合にさまざまな影響を及ぼす可能性のある、いくつかの一般的なオブジェクトタイプについて説明します。

次の表は、オブジェクトタイプとその潜在的な影響の概要を示しています。


**オブジェクトタイプと潜在的な影響**  

| オブジェクトのタイプ | autovacuum | 論理レプリケーション | メジャーバージョンアップグレード | pg\$1dump / pg\$1restore | 全般的なパフォーマンス | インスタンスの再起動 | 
| --- | --- | --- | --- | --- | --- | --- | 
| [リレーション](#PostgreSQL.HighObjectCount.Relations) | x |  | x | x | x |  | 
| [一時テーブル](#PostgreSQL.HighObjectCount.TempTables)。 | x |  |  |  | x |  | 
| [ログに記録されないテーブル](#PostgreSQL.HighObjectCount.UnloggedTables) |  | x |  |  |  | x | 
| [パーティション](#PostgreSQL.HighObjectCount.Partitions) |  |  |  |  | x |  | 
| [一時ファイル](#PostgreSQL.HighObjectCount.TempFiles) |  |  |  |  | x |  | 
| [シーケンス](#PostgreSQL.HighObjectCount.Sequences) |  | x |  |  |  |  | 
| [ラージオブジェクト](#PostgreSQL.HighObjectCount.LargeObjects) |  | x | x |  |  |  | 

## リレーション
<a name="PostgreSQL.HighObjectCount.Relations"></a>

PostgreSQL データベース内のテーブル数に特定のハード制限はありません。理論上の制限は非常に高いですが、データベース設計時に留意する必要がある実用的な制限が他にもあります。

**影響: autovacuum が遅れる**  
autovacuum は、作業量と比較してワーカーが不足しているため、トランザクション ID の増加やテーブルの肥大化に対応しきれない可能性があります。  
**推奨されるアクション:** autovacuum をチューニングして、特定の数のテーブルと特定のワークロードに適切に対応させるには、いくつかの要素を考慮する必要があります。適切な autovacuum 設定を決定する方法については、「[PostgreSQL autovacuum を使用するためのベストプラクティス](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum.html)」を参照してください。[postgres\$1get\$1av\$1diag ユーティリティ](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Autovacuum_Monitoring.Functions.html)を使用して、トランザクション ID の増加に関する問題をモニタリングします。

**影響: メジャーバージョンのアップグレード/pg\$1dump と復元**  
Amazon RDS は、pg\$1upgrade の実行中に「--link」オプションを使用して、データファイルのコピーを作成する必要がないようにしますが、スキーマメタデータは新しいバージョンのデータベースに復元する必要があります。並列 pg\$1restore を使用しても、リレーションの数が多いとダウンタイムが増加します。

**影響: 一般的なパフォーマンスの低下**  
カタログサイズによる一般的なパフォーマンスの低下。各テーブルとそれに関連する列は、`pg_attribute`、`pg_class`、および通常のデータベースオペレーションで頻繁に使用される `pg_depend` テーブルに追加されます。特定の待機イベントは表示されませんが、共有バッファの効率に影響します。  
**推奨されるアクション:** これらの特定のテーブルに対してテーブルの肥大化を定期的にチェックし、必要に応じてこれらの特定のテーブルに `VACUUM FULL` を実行します。カタログテーブルの `VACUUM FULL` では `ACCESS EXCLUSIVE` ロックが必要です。これは、オペレーションが完了するまで他のクエリがそれらにアクセスできないことを意味します。

**影響: ファイル記述子の枯渇**  
エラー: 「ファイル記述子不足: システムで開いているファイルが多すぎます。ファイルを解放して再試行してください」。PostgreSQL のパラメータ `max_files_per_process` は、各プロセスが開くことができるファイルの数を決定します。多数のテーブルを結合する接続の数が多い場合、この制限に達する可能性があります。  
**推奨されるアクション:**  
+ パラメータ `max_files_per_process` の値を下げると、このエラーを軽減できる可能性があります。各プロセスとサブプロセス (並列クエリなど) は、この数のファイルを開くことができ、クエリが複数のテーブルを結合している場合は、この制限を超える可能性があります。
+ 接続の総数を減らし、[Amazon RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html) などの接続プーラー、または PgBouncer などの他のソリューションを使用します。詳細については、[PGBouncer](https://www.pgbouncer.org/) のウェブサイトを参照してください。

**影響: Inode の枯渇**  
エラー: 「デバイスに空き容量がありません」。ストレージの空き領域が大量にある場合にこれが観察された場合は、inode が不足していることが原因です。[Amazon RDS 拡張モニタリング](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html)は、使用中の inode とホストで使用できる最大数を可視化します。

**概算しきい値:** [数百万](#PostgreSQL.HighObjectCount.Note)

## 一時テーブル
<a name="PostgreSQL.HighObjectCount.TempTables"></a>

一時テーブルの使用は、テストデータまたは中間結果に役立ち、多くのデータベースエンジンで見られる一般的なパターンです。PostgreSQL での大量使用の影響を理解して、いくつかの落とし穴を回避する必要があります。一時テーブルの作成と削除ごとに、システムカタログテーブルに行が追加され、肥大化すると、一般的なパフォーマンスの問題が発生します。

**影響: autovacuum が遅れる**  
一時テーブルは autovacuum によってバキューム処理されませんが、存在中はトランザクション ID を保持し、削除しないと循環が発生する可能性があります。  
**推奨されるアクション:** 一時テーブルは、それらを作成したセッション期間中存続するか、手動で削除できます。ベストプラクティスとして、一時テーブルを使用する際に長時間実行されるトランザクションを避けることで、これらのテーブルが使用済みトランザクション ID の最大値の増加に寄与するのを防ぐことができます。

**影響: 一般的なパフォーマンスの低下**  
カタログサイズによる一般的なパフォーマンスの低下。セッションが継続的に一時テーブルを作成および削除すると、通常のデータベースオペレーションで頻繁に使用される `pg_attribute`、`pg_class`、`pg_depend` テーブルにテーブルが追加されます。特定の待機イベントは表示されませんが、共有バッファの効率に影響します。  
**推奨されるアクション:**  
+ これらの特定のテーブルに対してテーブルの肥大化を定期的にチェックし、必要に応じてこれらの特定のテーブルに `VACUUM FULL` を実行します。カタログテーブルの `VACUUM FULL` では `ACCESS EXCLUSIVE` ロックが必要です。これは、オペレーションが完了するまで他のクエリがそれらにアクセスできないことを意味します。
+ 一時テーブルが頻繁に使用される場合は、メジャーバージョンアップグレードの前に、ダウンタイムを短縮するために、これらの特定のカタログテーブルの `VACUUM FULL` を強くお勧めします。

**一般的なベストプラクティス:**
+ 共通テーブル式を使用して中間結果を生成することで、一時テーブルの使用を減らします。これらは、必要なクエリを複雑にすることがありますが、上記の影響を排除できます。
+ `TRUNCATE` コマンドを使用して一時テーブルを再利用し、ドロップ/作成ステップを実行する代わりに内容をクリアします。これにより、一時テーブルによるトランザクション ID の増加の問題も排除されます。

**概算しきい値:** [数万](#PostgreSQL.HighObjectCount.Note)

## ログに記録されないテーブル
<a name="PostgreSQL.HighObjectCount.UnloggedTables"></a>

ログに記録されないテーブルは、WAL 情報を生成しないため、パフォーマンスを向上させることができます。これらはデータベースのクラッシュ回復中に切り捨てられるため、耐久性がなく、慎重に使用する必要があります。これは PostgreSQL ではコストの高いオペレーションであり、ログに記録されていない各テーブルは順次切り捨てられます。このオペレーションはログに記録されないテーブルの数が少ない場合は高速ですが、数千のテーブルの数になると、起動中に顕著な遅延が発生し始める可能性があります。

**影響: 論理レプリケーション**  
論理レプリケーションでは WAL を利用して変更をキャプチャおよび転送するため、ログに記録されないテーブルは通常、[ブルー/グリーンデプロイ](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments.html)を含む論理レプリケーションに含まれません。

  


**影響: 復旧中のダウンタイムが長引く**  
フェイルオーバーによるマルチ AZ 再起動、Amazon RDS ポイントインタイムリカバリ、Amazon RDS メジャーバージョンアップグレードなどのデータベースのクラッシュ回復を含むデータベース状態においては、ログに記録されないテーブルを切り捨てるシリアル化されたオペレーションが発生します。これにより、予想よりもはるかに高いダウンタイムが発生する可能性があります。  
**推奨されるアクション:**  
+ ログに記録されないテーブルの使用は、データベースのクラッシュ回復オペレーション中に失われても許容できるデータのみに限定するようにしてください。
+ シリアル切り捨ての現在の動作により、データベースの起動にかなりの時間がかかる可能性があるため、ログに記録されないテーブルの使用は最小限に抑えてください。

**一般的なベストプラクティス:**
+ ログに記録されないテーブルはクラッシュ時に安全性が確保されません。クラッシュ回復を伴うポイントインタイムリカバリの開始は、各テーブルを切り捨てるシリアルプロセスであるため、PostgreSQL ではかなりの時間がかかります。

**概算しきい値:** [数千](#PostgreSQL.HighObjectCount.Note)

## パーティション
<a name="PostgreSQL.HighObjectCount.Partitions"></a>

パーティション分割により、クエリのパフォーマンスが向上し、データの論理的な整理が可能になります。理想的なシナリオでは、パーティション分割は、クエリの計画と実行時にパーティションプルーニングを使用できるように構成されます。パーティションが多すぎると、クエリのパフォーマンスとデータベースのメンテナンスに悪影響を及ぼす可能性があります。クエリの計画と実行のパフォーマンスは、不十分な設計によって悪影響を受ける可能性があるため、テーブルを分割する方法の選択は慎重に行う必要があります。パーティション分割の詳細については、[PostgreSQL のドキュメント](https://www.postgresql.org/docs/current/ddl-partitioning.html)を参照してください。

**影響: 一般的なパフォーマンスの低下**  
場合によっては、計画時間のオーバーヘッドが増加し、クエリの実行計画がより複雑になり、チューニングの機会を特定することが難しくなる場合があります。18 より前の PostgreSQL バージョンでは、ワークロードの高いパーティションが多いと、`LWLock:LockManager` 待機につながる可能性があります。  
**推奨されるアクション:** データの整理を完了させると同時に、クエリの実行パフォーマンスも向上させるために必要な最小限のパーティション数を決定します。

**影響: メンテナンスの複雑さ**  
パーティションの数が非常に多いと、事前作成や削除などのメンテナンスの問題が発生します。autovacuum はパーティションを通常のリレーションとして扱い、定期的なクリーンアップを実行する必要があるため、タスクを完了するのに十分なワーカーが必要です。  
**推奨されるアクション:**  
+ 新しいパーティションが必要になったとき (月単位のパーティションなど) や古いパーティションがロールオフされたときにワークロードがブロックされないように、パーティションを事前に作成してください。
+ すべてのパーティションの通常のクリーンアップメンテナンスを実行するのに十分な autovacuum ワーカーがあることを確認します。

**概算しきい値:** [数百](#PostgreSQL.HighObjectCount.Note)

## 一時ファイル
<a name="PostgreSQL.HighObjectCount.TempFiles"></a>

上記の一時テーブルとは異なり、一時ファイルは、複雑なクエリが複数のソート操作またはハッシュ操作を同時に実行する可能性がある場合に PostgreSQL によって作成されます。各オペレーションは、インスタンスメモリを使用して `work_mem` パラメータで指定された値までの結果を保存します。インスタンスメモリが不足すると、結果を保存する一時ファイルが作成されます。一時ファイルの詳細については、「[一時ファイルの管理](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL.ManagingTempFiles.html)」を参照してください。ワークロードがこれらのファイルを大量に生成する場合、いくつかの影響が生じる可能性があります。

  


**影響: ファイル記述子の枯渇**  
エラー: 「ファイル記述子不足: システムで開いているファイルが多すぎます。ファイルを解放して再試行してください」。PostgreSQL のパラメータ `max_files_per_process` は、各プロセスが開くことができるファイルの数を決定します。多数のテーブルを結合する接続の数が多い場合、この制限に達する可能性があります。  
**推奨されるアクション:**  
+ パラメータ `max_files_per_process` の値を下げると、このエラーを軽減できる可能性があります。各プロセスとサブプロセス (並列クエリなど) は、この数のファイルを開くことができ、クエリが複数のテーブルを結合している場合は、この制限を超える可能性があります。
+ 接続の総数を減らし、[Amazon RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html) などの接続プーラーや PgBouncer などの他のソリューションを使用します。詳細については、[PGBouncer](https://www.pgbouncer.org/) のウェブサイトを参照してください。

**影響: Inode の枯渇**  
エラー: 「デバイスに空き容量がありません」。ストレージの空き領域が大量にある場合にこれが観察された場合は、inode が不足していることが原因です。[Amazon RDS 拡張モニタリング](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html)は、使用中の inode とホストで使用できる最大数を可視化します。

**一般的なベストプラクティス:**
+ [Performance Insights](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PerfInsights.html) を使用して一時ファイルの使用状況をモニタリングします。
+ 大量の一時ファイルを生成しているクエリを調整して、一時ファイルの合計数を減らすことができるかどうかを確認します。

**概算しきい値:** [数千](#PostgreSQL.HighObjectCount.Note)

## シーケンス
<a name="PostgreSQL.HighObjectCount.Sequences"></a>

シーケンスは、PostgreSQL の列の自動増分に使用される基盤となるオブジェクトであり、データの一意性とキーを提供します。これらは、論理レプリケーションを 1 つ例外として、通常のオペレーション中に特に影響を与えることなく、個々のテーブルで使用できます。

PostgreSQL では、論理レプリケーションは現在、シーケンスの現在の値をサブスクライバーにレプリケートしません。詳細については、[PostgreSQL のドキュメントの制約事項ページ](https://www.postgresql.org/docs/current/logical-replication-restrictions.html)を参照してください。

**影響: スイッチオーバー時間の延長**  
任意のタイプの設定変更またはアップグレードに、[Amazon RDS ブルー/グリーンデプロイ](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments.html)を使用する予定がある場合は、多数のシーケンスがスイッチオーバーに与える影響を理解することが重要です。スイッチオーバーの最後のフェーズの 1 つとして、シーケンスの現在の値を同期させる処理が行われますが、その数が数千に及ぶ場合、スイッチオーバー全体の所要時間が長くなります。  
**推奨されるアクション:** データベースワークロードがテーブルごとのシーケンスアプローチではなく共有 UUID の使用を許可する場合、スイッチオーバー中に同期ステップを削減できます。

**概算しきい値:** [数千](#PostgreSQL.HighObjectCount.Note)

## ラージオブジェクト
<a name="PostgreSQL.HighObjectCount.LargeObjects"></a>

ラージオブジェクトは pg\$1largeobject という名前の単一のシステムテーブルに保存されます。各ラージオブジェクトには、システムテーブル pg\$1largeobject\$1metadata にもエントリがあります。これらのオブジェクトは、標準リレーションとは大幅に異なる方法で作成、変更、クリーンアップされます。ラージオブジェクトは autovacuum では処理されないため、vacuumlo と呼ばれる別のプロセスで定期的にクリーンアップする必要があります。ラージオブジェクトの管理の例については、「lo モジュールを使用したラージオブジェクトの管理」を参照してください。

**影響: 論理レプリケーション**  
現在、PostgreSQL では論理レプリケーション時にラージオブジェクトはレプリケートされません。詳細については、[PostgreSQL のドキュメントの制約事項ページ](https://www.postgresql.org/docs/current/logical-replication-restrictions.html)を参照してください。[ブルー/グリーン](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments.html)設定では、ブルー環境内のラージオブジェクトはグリーン環境にレプリケートされません。

**影響: メジャーバージョンアップグレード**  
数百万のラージオブジェクトがあり、アップグレード中にインスタンスがそれらを処理できない場合、アップグレードはメモリ不足になり、失敗する可能性があります。PostgreSQL メジャーバージョンのアップグレードプロセスは、大きく分けて 2 つのフェーズで構成されます。pg\$1dump によるスキーマダンプと、pg\$1restore による復元です。データベースに数百万のラージオブジェクトがある場合は、アップグレード中に pg\$1dump と pg\$1restore を処理するために十分なメモリがインスタンスにあることを確認し、より大きなインスタンスタイプにスケールする必要があります。

**一般的なベストプラクティス:**
+ vacuumlo ユーティリティを定期的に使用して、孤立したラージオブジェクトを削除します。
+ ラージオブジェクトをデータベースに保存する場合は、BYTEA データ型を使用することを検討してください。

**概算しきい値:** [数百万](#PostgreSQL.HighObjectCount.Note)

## 概算しきい値
<a name="PostgreSQL.HighObjectCount.Note"></a>

このトピックで説明されている概算しきい値は、特定のリソースがスケールできる範囲を推定するためにのみ使用されます。これらは、説明されている影響が発生する可能性が高くなる一般的な範囲を示していますが、実際の動作は、特定のワークロード、インスタンスサイズ、および設定によって異なります。これらの予測を超える可能性はあるものの、記載されている影響を避けるためには、適切な管理とメンテナンスを遵守する必要があります。