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的实现原理如下:
    1. 创建日志表,记录对原表的变更。
    2. 在原表上创建触发器,将原表的INSERTUPDATEDELETE操作记录到日志表中。
    3. 创建并导入与原表结构相同的新表。
    4. 在新表中创建原表上的索引。
    5. 将日志表里的变更应用到新表。
    6. 在系统catalog交换新旧表。
    7. 删除旧表。
    说明 pg_repack会在第1、2步和第6、7步短暂持有ACCESS EXCLUSIVE锁。其余步骤pg_repack只需要持有原表的ACCESS SHARE锁,不影响对原表的INSERT、UPDATE和DELETE操作。
  • 对索引进行repack的实现原理如下:
    1. CONCURRENTLY方式创建新索引。
    2. 在系统catalog交换新旧索引。
    3. 删除旧索引。

插件开启与关闭

  • 开启插件。
    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官方帮助文档