RDS PostgreSQL表存储空间缩容

随着数据库的运行,表内部会产生大量的空间碎片。RDS PostgreSQL自带的autovacuum功能仅能整理每个页面(page)内部的空间,而无法有效减少页面数量,从而释放磁盘空间。因此,可以使用VACUUM FULL、pg_repackpg_squeeze来实现RDS PostgreSQL数据库的表空间缩容。

功能介绍

  • autovacuumVACUUM FULL、pg_repack以及pg_squeeze的清理效果比较:

    image
  • VACUUM FULL、pg_repackpg_squeeze缩容对比:

    缩容方式

    优点

    限制

    适用场景

    VACUUM FULL

    对被清理的表没有特定要求,且无需额外安装插件。

    在执行过程中,VACUUM FULL会对目标表加上排他锁,导致在执行期间无法访问该表。

    目标表的数据可以在特定时间段内暂停使用。

    pg_repack

    重建表的同时不会阻塞数据的增删改查操作。

    • 重建的表必须具有主键或唯一键。

    • 需要安装pg_repack插件。

    • 需要在本地安装pg_repack客户端,并通过该客户端连接数据库进行repack操作。

    目标表的数据修改频率较高。

    pg_squeeze

    重建表的同时不会阻塞数据的增删改查操作。

    • 要求被清理的表必须具有主键或唯一键。

    • 需要安装pg_squeeze插件,但不需要在本地安装客户端。

    • 当有持续大量数据增量写入,pg_squeeze可能无法完成操作。

    目标表的数据修改频率较低。

VACUUM FULL

VACUUM FULLPostgreSQL社区提供的重建表命令。该命令会生成目标表的副本,并在完成后删除原始表。尽管对被清理的表没有特殊要求,但其缺点也十分明显。在执行过程中,VACUUM FULL会对该表加上排他锁,导致在执行期间无法访问该表,给许多线上业务造成显著影响。

pg_repack

pg_repack有效地解决了VACUUM FULL带来的问题,在重建表的同时不会阻塞数据的增删改查操作。然而,它也存在一些局限性,例如重建的表必须具有主键或唯一键。此外,pg_repack的使用相对复杂,需要在本地安装pg_repack客户端,并通过该客户端连接数据库进行repack操作,这可能在生产环境中造成不便。

pg_repack通过分别处理存量和增量数据的方式实现了上述功能。

  1. 处理存量数据,生成原表的快照副本,即新表。

  2. 处理增量数据,通过触发器,持续将新生成的数据存储至临时表中。

  3. 确保增量数据已被完全处理。在新表创建完成后,会将临时表中的增量数据应用至新表,直到临时表为空,确认所有增量数据均已转移。

pg_repack的使用方法请参见pg_repack

pg_squeeze

pg_repack相似,pg_squeeze同样能够在不阻塞增删改查操作的情况下进行数据清理,并要求被清理的表必须具有主键或唯一键。相较于pg_repack,pg_squeeze的使用更加简便,仅需在数据库中创建相应的插件即可。此外,它还具备自动检测和触发清理的功能。

pg_squeeze的原理与pg_repack相似,但在保存增量数据时存在不同之处。pg_squeeze通过逻辑复制将增量数据存储于PostgreSQL的内部数据结构中,而pg_repack则是通过触发器将数据存入临时表。

pg_squeeze的使用方法请参见pg_squeeze

pg_repackpg_squeeze性能对比

这两者功能相同,且限制条件相似。在生产环境中选择时,如果两者均可用,性能将成为重要参考依据。

在清理期间,如果没有增量数据,两者性能相当;若存在固定增量数据,pg_squeeze 的性能稍优于 pg_repack;但若有持续大量数据增量写入,pg_squeeze 可能无法完成操作。

pg_squeeze会将表的写入性能降低至原来的50%,而pg_repack 则降低至10%。pg_repack利用触发器和临时表存放增量数据,在执行期间写入速度明显减慢,因此可以消耗完所有增量数据。在pg_squeeze执行期间,增量数据的产生速度可能超出应用处理速度,从而导致无法完全消耗所有增量数据。

因此,建议在修改频繁的表上使用pg_repack,而在其他场景中则更适宜采用pg_squeeze。