云数据库 PostgreSQL 支持通过插件 pg_repack 在线清理表空间,有效解决因对全表大量更新等操作引起的表膨胀问题。与 CLUSTER 和 VACUUM 不同,pg_repack 在线运行,处理过程中无需在已处理的表上持有独占锁,同时 pg_repack 启动效率高,性能与直接使用 CLUSTER 相当。本文将详细介绍如何通过 pg_repack 处理表膨胀。更多的 pg_repack 使用场景请参考 官方文档。
注意:
pg_repack 需要额外的存储空间。全表 repack 时,剩余存储空间大小需要至少是待 repack 表大小的2倍,请提前升级云数据库 PostgreSQL 实例配置。
pg_repack 无法操作临时表、无法操作 GiST 索引。
pg_repack 运行时会持有 ACCESS SHARE 锁,无法对 repack 操作中的表执行 DDL。
重建表和索引时会占用较多的磁盘 IO,请在业务低峰期执行。
目标表必须具有 PRIMARY KEY,或者至少在 NOT NULL 列上具有 UNIQUE 总索引。
前置条件
已有一个云数据库 PostgreSQL 实例,创建请参考 创建 PostgreSQL 实例。
该实例已安装 pg_repack 插件,安装请参考 如何在云数据库 PostgreSQL 实例中创建插件。
已有一台云服务器 CVM ,该云服务器跟云数据库 PostgreSQL 实例在同一个 VPC 网络。Linux 系统的云服务器配置请参见 快速配置 Linux 云服务器。
云服务器 CVM 实例已安装 psql 客户端,详细安装教程请参考 PostgreSQL 官方文档。
安装客户端
unzip pg_repack-1.5.2.zipcd pg_repack-1.5.2make && make install
清理单表
-- 检查但不执行pg_repack -k --dry-run --no-order -h 10.*.*.* -p 5432 -U user -d database -t schema1.table1-- 检查并执行pg_repack -k --no-order -h 10.*.*.* -p 5432 -U user -d database -t schema1.table1
清理单个 schema
-- 检查但不执行pg_repack -k --dry-run --no-order -h 10.*.*.* -p 5432 -U user -d database -c schema-- 检查并执行pg_repack -k --no-order -h 10.*.*.* -p 5432 -U user -d database -c schema
清理单个库
-- 检查但不执行pg_repack -k --dry-run --no-order -h 10.*.*.* -p 5432 -U user -d database-- 检查并执行pg_repack -k --no-order -h 10.*.*.* -p 5432 -U user -d database
清理整个实例(仅清理安装 pg_repack 插件的数据库)
-- 检查但不执行pg_repack -k --dry-run --no-order -h 10.*.*.* -p 5432 -U user -a-- 检查并执行pg_repack -k --no-order -h 10.*.*.* -p 5432 -U user -a
检查清理效果
-- 查看库大小top,sql如下:select datname,pg_size_pretty(pg_database_size(datname)) from pg_database order by pg_database_size(datname) desc;-- 查看库中表大小top,sql如下:SELECT relname AS table_name, pg_size_pretty(pg_total_relation_size(relid)) AS total_size FROM pg_catalog.pg_statio_user_tables ORDER BY pg_total_relation_size(relid) DESC;-- 查看特定表的大小,sql如下:select pg_size_pretty(pg_total_relation_size('pgtest'));