

# 管理 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 utility](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` 锁，这意味着在操作完成之前，任何其它查询都无法访问这些表。

**影响：文件描述符耗尽**  
错误：“out of file descriptors: Too many open files in system; release and retry”。PostgreSQL `max_files_per_process` 参数决定了每个进程可以打开多少个文件。如果有大量的连接加入大量的表，则有可能达到此限制。  
**建议的操作：**  
+ 降低 `max_files_per_process` 参数的值可能有助于缓解此错误。每个进程和子进程（例如，并行查询）可以打开此数量的文件，如果查询要联接多个表，则此限制可能会耗尽。
+ 减少连接总数并使用连接池程序，例如 [Amazon RDS 代理](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html)或其它解决方案（如 PgBouncer）。要了解更多信息，请参阅 [PGBouncer](https://www.pgbouncer.org/) 网站。

**影响：索引节点耗尽**  
错误：“设备上没有剩余空间”。如果在有充足的可用存储空间时观察到这种情况，则这是由于索引节点用完所致。[Amazon RDS 增强监控](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html)会显示正在使用的索引节点以及可用于主机的最大数量。

**近似阈值：**[百万](#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 中，这是一项代价高昂的操作，因为每个未记录的表都会依次被截断。虽然对于少量未记录的表来说，此操作速度很快，但当它们的数量达到数千个时，可能会在启动过程中开始增加明显的延迟。

**影响：逻辑复制**  
逻辑复制中通常不包括未记录的表，包括[蓝绿部署](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments.html)，因为逻辑复制依赖于 WAL 来捕获和传输更改。

  


**影响：恢复期间的停机时间延长**  
在任何涉及数据库崩溃恢复的数据库状态（例如带失效转移的多可用区重启、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)。如果您的工作负载生成了大量此类文件，则可能会产生多种影响。

  


**影响：文件描述符耗尽**  
错误：“out of file descriptors: Too many open files in system; release and retry”。PostgreSQL `max_files_per_process` 参数决定了每个进程可以打开多少个文件。如果有大量的连接加入大量的表，则有可能达到此限制。  
**建议的操作：**  
+ 降低 `max_files_per_process` 参数的值可能有助于缓解此错误。每个进程和子进程（例如，并行查询）可以打开此数量的文件，如果查询要联接多个表，则此限制可能会耗尽。
+ 减少连接总数并使用连接池程序（例如 [Amazon RDS 代理](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html)）或其它解决方案（如 PgBouncer）。要了解更多信息，请参阅 [PGBouncer](https://www.pgbouncer.org/) 网站。

**影响：索引节点耗尽**  
错误：“设备上没有剩余空间”。如果在有充足的可用存储空间时观察到这种情况，则这是由于索引节点用完所致。[Amazon RDS 增强监控](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html)会显示正在使用的索引节点以及可用于主机的最大数量。

**一般最佳实践：**
+ 使用[性能详情](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PerfInsights.html)监控临时文件使用情况。
+ 调优生成大量临时文件的查询，以查看是否可能减少临时文件总数。

**近似阈值：**[数千](#PostgreSQL.HighObjectCount.Note)

## 序列
<a name="PostgreSQL.HighObjectCount.Sequences"></a>

序列是 PostgreSQL 中用于自动递增列的底层对象，它们为数据提供了唯一性和密钥。这些序列可以在单独的表上使用，在正常操作期间不会产生任何后果，但逻辑复制除外。

在 PostgreSQL 中，逻辑复制当前不会将序列的当前值复制到任何订阅用户。要了解更多信息，请参阅 [PostgreSQL 文档中的“Restrictions”页面](https://www.postgresql.org/docs/current/logical-replication-restrictions.html)。

**影响：切换时间延长**  
如果您计划使用[ Amazon RDS 蓝绿部署](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments.html)进行任何类型的配置更改或升级，请务必了解大量的序列对切换的影响。切换的最后阶段之一会同步序列的当前值，如果数量达几千个，这将增加总体切换时间。  
**建议的操作：**如果您的数据库工作负载支持使用共享 UUID 而不是按表排序的方法，这将削减切换期间的同步步骤。

**近似阈值：**[数千](#PostgreSQL.HighObjectCount.Note)

## 大型对象
<a name="PostgreSQL.HighObjectCount.LargeObjects"></a>

大型对象存储在名为 pg\$1largeobject 的单个系统表中。每个大型对象在系统表 pg\$1largeobject\$1metadata 中也有一个条目。这些对象的创建、修改和清理方式与标准关系大不相同。大型对象不是通过 autovacuum 处理，而必须通过名为 vacuumlo 的单独进程定期清理。有关管理大型对象的示例，请参阅“使用 lo 模块管理大型对象”。

**影响：逻辑复制**  
在逻辑复制期间，当前不会在 PostgreSQL 中复制大型对象。要了解更多信息，请参阅 [PostgreSQL 文档中的“Restrictions”页面](https://www.postgresql.org/docs/current/logical-replication-restrictions.html)。在[蓝绿](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments.html)配置中，这意味着蓝色环境中的大型对象不会复制到绿色环境中。

**影响：主要版本升级**  
如果有数百万个大型对象，并且实例在升级期间无法处理它们，则升级可能会耗尽内存并失败。PostgreSQL 主要版本升级过程包括两个主要阶段：通过 pg\$1dump 转储架构和通过 pg\$1restore 还原架构。如果数据库具有数百万个大型对象，则您需要确保实例具有足够的内存，可在升级期间处理 pg\$1dump 和 pg\$1restore，并将其扩展到更大的实例类型。

**一般最佳实践：**
+ 定期使用 vacuumlo 实用程序移除您可能拥有的任何孤立的大型对象。
+ 考虑使用 BYTEA 数据类型来将大型对象存储在数据库中。

**近似阈值：**[百万](#PostgreSQL.HighObjectCount.Note)

## 近似阈值
<a name="PostgreSQL.HighObjectCount.Note"></a>

本主题中提到的近似阈值仅用于估算特定资源可以扩展到多大程度。它们代表了更有可能受到上述影响的一般范围，但实际行为取决于您的特定工作负载、实例大小和配置。虽然可能超过这些估算值，但必须坚持谨慎行事并进行维护，以避免所列的影响。