PolarDB PostgreSQL版(兼容Oracle)支持通过pg_repack插件对表空间进行重新“包装”,回收碎片空间,有效解决因对全表大量更新等操作引起的表膨胀问题。pg_repack无需获取排它锁,相比CLUSTER或VACUUM FULL更加轻量化。
注意事项
- pg_repack需要额外的存储空间。全表repack时,剩余存储空间大小需要至少是被repack的表大小的2倍。
- pg_repack无法对临时表进行repack操作。
- pg_repack无法对GiST索引进行repack操作。
- pg_repack运行时无法对正在进行repack的表执行DDL操作。由于repack过程会持有ACCESS SHARE锁,会阻塞DDL执行。
- 对表和索引进行repack操作时会占用较多的磁盘IO,使用时请提前评估是否影响业务。以PL1级别的ESSD云盘为例,对一个100GB的表进行repack时,会达到IO吞吐上限(250MB/s)。
- pg_repack插件赖于客户端工具,需要先安装pg_repack客户端,然后通过命令行使用pg_repack插件。
功能介绍
pg_repack插件支持对全表和索引进行repack操作。
- 对全表进行repack的实现原理如下:
- 创建日志表,记录对原表的变更。
- 在原表上创建触发器,将原表的
INSERT
、UPDATE
和DELETE
操作记录到日志表中。 - 创建并导入与原表结构相同的新表。
- 在新表中创建原表上的索引。
- 将日志表里的变更应用到新表。
- 在系统catalog交换新旧表。
- 删除旧表。
说明 pg_repack会在第1、2步和第6、7步短暂持有ACCESS EXCLUSIVE锁。其余步骤pg_repack只需要持有原表的ACCESS SHARE锁,不影响对原表的INSERT、UPDATE和DELETE操作。 - 对索引进行repack的实现原理如下:
- 以
CONCURRENTLY
方式创建新索引。 - 在系统catalog交换新旧索引。
- 删除旧索引。
- 以
插件开启与关闭
- 开启插件。
CREATE EXTENSION pg_repack;
- 关闭插件。
DROP EXTENSION pg_repack;
安装客户端
pg_repack插件需要配合客户端使用,pg_repack客户端的安装方式参考如下:
- CentOS 7
sudo yum install centos-release-scl-rh sudo yum install rh-postgresql12-pg_repack
- CentOS 8
sudo dnf install pg_repack
- Ubuntu 20.04/22.04
sudo apt install postgresql-11-repack
使用示例
-- 只检查pg_repack是否正确,不实际执行:--dry-run
$ pg_repack --dry-run \
--no-superuser-check --echo --no-order \
-h 连接串 -p 端口 -d database1 -U user --table schema1.table1
-- 实际执行
$ pg_repack \
--no-superuser-check --echo --no-order \
-h 连接串 -p 端口 -d database1 -U user --table schema1.table1
说明 PolarDB PostgreSQL版(兼容Oracle)不允许直接创建tablespace,所以无法使用pg_repack的
-s
/--tablespace
选项对指定的tablespace进行repack操作。相关参考
pg_repack的更多信息可参考pg_repack官方帮助文档。