随着数据库的运行,表内部会产生大量的空间碎片。RDS PostgreSQL自带的autovacuum功能仅能整理每个页面(page)内部的空间,而无法有效减少页面数量,从而释放磁盘空间。因此,可以使用VACUUM FULL、pg_repack和pg_squeeze来实现RDS PostgreSQL数据库的表空间缩容。
功能介绍
autovacuum与VACUUM FULL、pg_repack以及pg_squeeze的清理效果比较:
VACUUM FULL、pg_repack和pg_squeeze缩容对比:
缩容方式
优点
限制
适用场景
VACUUM FULL
对被清理的表没有特定要求,且无需额外安装插件。
在执行过程中,VACUUM FULL会对目标表加上排他锁,导致在执行期间无法访问该表。
目标表的数据可以在特定时间段内暂停使用。
pg_repack
重建表的同时不会阻塞数据的增删改查操作。
重建的表必须具有主键或唯一键。
需要安装pg_repack插件。
需要在本地安装pg_repack客户端,并通过该客户端连接数据库进行repack操作。
目标表的数据修改频率较高。
pg_squeeze
重建表的同时不会阻塞数据的增删改查操作。
要求被清理的表必须具有主键或唯一键。
需要安装pg_squeeze插件,但不需要在本地安装客户端。
当有持续大量数据增量写入,pg_squeeze可能无法完成操作。
目标表的数据修改频率较低。
VACUUM FULL
VACUUM FULL是PostgreSQL社区提供的重建表命令。该命令会生成目标表的副本,并在完成后删除原始表。尽管对被清理的表没有特殊要求,但其缺点也十分明显。在执行过程中,VACUUM FULL会对该表加上排他锁,导致在执行期间无法访问该表,给许多线上业务造成显著影响。
pg_repack
pg_repack有效地解决了VACUUM FULL带来的问题,在重建表的同时不会阻塞数据的增删改查操作。然而,它也存在一些局限性,例如重建的表必须具有主键或唯一键。此外,pg_repack的使用相对复杂,需要在本地安装pg_repack客户端,并通过该客户端连接数据库进行repack操作,这可能在生产环境中造成不便。
pg_repack通过分别处理存量和增量数据的方式实现了上述功能。
处理存量数据,生成原表的快照副本,即新表。
处理增量数据,通过触发器,持续将新生成的数据存储至临时表中。
确保增量数据已被完全处理。在新表创建完成后,会将临时表中的增量数据应用至新表,直到临时表为空,确认所有增量数据均已转移。
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_repack和pg_squeeze性能对比
这两者功能相同,且限制条件相似。在生产环境中选择时,如果两者均可用,性能将成为重要参考依据。
在清理期间,如果没有增量数据,两者性能相当;若存在固定增量数据,pg_squeeze 的性能稍优于 pg_repack;但若有持续大量数据增量写入,pg_squeeze 可能无法完成操作。
pg_squeeze会将表的写入性能降低至原来的50%,而pg_repack 则降低至10%。pg_repack利用触发器和临时表存放增量数据,在执行期间写入速度明显减慢,因此可以消耗完所有增量数据。在pg_squeeze执行期间,增量数据的产生速度可能超出应用处理速度,从而导致无法完全消耗所有增量数据。
因此,建议在修改频繁的表上使用pg_repack,而在其他场景中则更适宜采用pg_squeeze。