管理 Amazon Aurora PostgreSQL 中的高对象计数
虽然 PostgreSQL 限制是理论上的,但数据库中的对象计数极高会对各种操作造成明显的性能影响。本文档介绍几种常见的对象类型,当对象的总计数较高时,可能会导致多种可能的影响。
下表概述了对象类型及其潜在影响:
关系
对 PostgreSQL 数据库中表的数量没有具体的硬性限制。理论上限极高,但在数据库设计过程中还需要记住其它实际限制。
- 影响:Autovacuum 滞后
-
由于工作线程不足以应对繁重的工作量,Autovacuum 可能难以跟上事务 ID 的增长或表膨胀。
建议的操作:要使 autovacuum 能够适应给定数量的表和给定的工作负载,需考虑多个调优因素。有关如何确定适当的 autovacuum 设置的建议,请参阅使用 PostgreSQL autovacuum 的最佳实践。使用 postgres_get_av_diag utility 来监控事务 ID 增长问题。
- 影响:主要版本升级/pg_dump 和还原
-
Amazon RDS 在 pg_upgrade 执行期间使用“--link”选项来避免必须复制数据文件,但仍需要将架构元数据还原到新版本的数据库中。即使使用并行 pg_restore,但如果存在大量的关系,这也将增加停机时间。
- 影响:一般性能降级
-
由于目录大小,导致一般性能降级。每个表及其关联的列将添加到
pg_attribute、pg_class和pg_depend表中,这些表在常规数据库操作中频繁使用。不会显示特定的等待事件,但共享缓冲区效率会受到影响。建议的操作:定期检查这些特定表的表膨胀情况,偶尔对这些特定的表执行
VACUUM FULL。请注意,对目录表执行VACUUM FULL需要ACCESS EXCLUSIVE锁,这意味着在操作完成之前,任何其它查询都无法访问这些表。
近似阈值:百万
临时表
使用临时表对测试数据或中间结果很有用,这是许多数据库引擎中常见的模式。必须了解在 PostgreSQL 中大量使用的影响,以避免一些陷阱。每个临时表创建和删除都会向系统目录表中添加行,当它们变得膨胀时,这将导致一般性能问题。
- 影响:Autovacuum 滞后
-
临时表不会被 autovacuum 清空,但会在它们存在期间保留事务 ID,如果不移除,可能会导致环绕。
建议的操作:临时表将在创建临时表的会话持续时间内生效,也可以手动删除它们。避免使用临时表执行长时间运行的事务的最佳实践,可防止这些表促成已用事务 ID 增长达到最大程度。
- 影响:一般性能降级
-
由于目录大小,导致一般性能降级。当会话不断地创建和删除临时表时,将会增加
pg_attribute、pg_class和pg_depend表的大小,正常数据库操作中会频繁使用这些表。不会显示特定的等待事件,但共享缓冲区效率会受到影响。建议的操作:
定期检查这些特定表的表膨胀情况,偶尔对这些特定的表执行
VACUUM FULL。请注意,对目录表执行VACUUM FULL需要ACCESS EXCLUSIVE锁,这意味着在操作完成之前,任何其它查询都无法访问这些表。如果大量使用临时表,则在主要版本升级之前,强烈建议对这些特定的目录表执行
VACUUM FULL,以减少停机时间。
一般最佳实践:
通过使用公用表表达式生成中间结果,减少临时表的使用。这些有时会使所需的查询复杂化,但会消除上面列出的影响。
通过使用
TRUNCATE命令清除内容,而不是执行删除/创建步骤,重用临时表。这也将消除由临时表导致的事务 ID 增长问题。
近似阈值:数万
未记录表
未记录的表可以提高性能,因为它们不会生成任何 WAL 信息。必须谨慎使用这些表,原因在于,它们在数据库崩溃恢复期间不会提供持久性,因为这些表会被截断。在 PostgreSQL 中,这是一项代价高昂的操作,因为每个未记录的表都会依次被截断。虽然对于少量未记录的表来说,此操作速度很快,但当它们的数量达到数千个时,可能会在启动过程中开始增加明显的延迟。
- 影响:逻辑复制
-
逻辑复制中通常不包括未记录的表,包括蓝绿部署,因为逻辑复制依赖于 WAL 来捕获和传输更改。详细了解如何配置 Aurora PostgreSQL 以复制未记录的表。
- 影响:读取器节点
-
您只能从 Aurora 数据库集群中的写入器节点访问未记录的表。有关完整详细信息,请参阅在 Aurora PostgreSQL 中使用未记录的表。
一般最佳实践:
-
与标准 PostgreSQL 相比,未记录的表在 Aurora PostgreSQL 中提供的性能优势有限,因此请评估普通表是否更合适。
近似阈值:数千
分区
分区可以提高查询性能并提供数据的逻辑组织。在理想情况下,分区的组织方式是为了便于在查询计划和执行期间使用分区修剪。使用过多的分区可能会对查询性能和数据库维护产生负面影响。应谨慎选择如何对表进行分区,因为不良的设计可能会对查询计划和执行的性能产生负面影响。有关分区的详细信息,请参阅 PostgreSQL 文档
- 影响:一般性能降级
-
有时,计划时间开销会增加,并且查询的解释计划会变得更加复杂,因此很难确定调优机会。对于版本 18 之前的 PostgreSQL 版本,许多工作负载较高的分区可能会导致
LWLock:LockManager等待。建议的操作:确定最少的分区数量,这样您既能完成数据的整理,同时又能提供高性能的查询执行。
- 影响:维护复杂性
-
分区数量过多会带来维护困难,例如预创建和移除。Autovacuum 会将分区视为正常关系,必须执行定期清理,因此需要足够的工作线程来完成该任务。
建议的操作:
确保预先创建分区,以便在需要新分区(例如,基于月度的分区)和回滚旧分区时不会阻塞工作负载。
确保有足够的 autovacuum 工作线程来对所有分区进行正常的清理维护。
近似阈值:数百
临时文件
与上述临时表不同,当一个复杂的查询可能同时执行多个排序或哈希操作时,PostgreSQL 会创建临时文件,每个操作都使用实例内存来存储结果,直至达到在 work_mem 参数中指定的值。当实例内存不足时,会创建临时文件来存储结果。有关临时文件的更多详细信息,请参阅管理临时文件。如果您的工作负载生成了大量此类文件,则可能会产生多种影响。
- 影响:FreeLocalStorage 消耗
-
当查询结果无法容纳在 work_mem 中时,临时文件是 PostgreSQL 的必要组成部分。一般来说,这是正常的。但是,当工作负载大量使用临时文件时,这表明大型查询持续运行,而且您将观察到 FreeLocalStorage 减少。有关更多详细信息,请参阅管理临时文件。
一般最佳实践:
使用性能详情监控临时文件使用情况。
调优生成大量临时文件的查询,以查看是否可能减少临时文件总数。
近似阈值:数千
序列
序列是 PostgreSQL 中用于自动递增列的底层对象,它们为数据提供了唯一性和密钥。这些序列可以在单独的表上使用,在正常操作期间不会产生任何后果,但逻辑复制除外。
在 PostgreSQL 中,逻辑复制当前不会将序列的当前值复制到任何订阅用户。要了解更多信息,请参阅 PostgreSQL 文档中的“Restrictions”页面
- 影响:切换时间延长
-
如果您计划使用蓝绿部署进行任何类型的配置更改或升级,请务必了解大量的序列对切换的影响。切换的最后阶段之一会同步序列的当前值,如果数量达几千个,这将增加总体切换时间。
建议的操作:如果您的数据库工作负载支持使用共享 UUID 而不是按表排序的方法,这将削减切换期间的同步步骤。
近似阈值:数千
大型对象
大型对象存储在名为 pg_largeobject 的单个系统表中。每个大型对象在系统表 pg_largeobject_metadata 中也有一个条目。这些对象的创建、修改和清理方式与标准关系大不相同。大型对象不是通过 autovacuum 处理,而必须通过名为 vacuumlo 的单独进程定期清理。有关管理大型对象的示例,请参阅“使用 lo 模块管理大型对象”。
- 影响:逻辑复制
-
在逻辑复制期间,当前不会在 PostgreSQL 中复制大型对象。要了解更多信息,请参阅 PostgreSQL 文档中的“Restrictions”页面
。在蓝绿配置中,这意味着蓝色环境中的大型对象不会复制到绿色环境中。 - 影响:主要版本升级
-
如果有数百万个大型对象,并且实例在升级期间无法处理它们,则升级可能会耗尽内存并失败。PostgreSQL 主要版本升级过程包括两个主要阶段:通过 pg_dump 转储架构和通过 pg_restore 还原架构。如果数据库具有数百万个大型对象,则您需要确保实例具有足够的内存,可在升级期间处理 pg_dump 和 pg_restore,并将其扩展到更大的实例类型。
一般最佳实践:
定期使用 vacuumlo 实用程序移除您可能拥有的任何孤立的大型对象。
考虑使用 BYTEA 数据类型来将大型对象存储在数据库中。
近似阈值:百万
近似阈值
本主题中提到的近似阈值仅用于估算特定资源可以扩展到多大程度。它们代表了更有可能受到上述影响的一般范围,但实际行为取决于您的特定工作负载、实例大小和配置。虽然可能超过这些估算值,但必须坚持谨慎行事并进行维护,以避免所列的影响。