概述
pg_repack插件对表空间进行重新“包装”,回收碎片空间,有效解决因对表大量更新、删除等操作引起的空间膨胀问题。pg_repack获取排它锁的时间较短,多数时间不阻塞读写,相比CLUSTER或VACUUM FULL操作更加轻量化。
安装依赖
yum install lz4-devel
安装编译
[root@test19-server07 opt]# wget https://github.com/reorg/pg_repack/archive/refs/tags/ver_1.5.1.tar.gz
shell > tar xvf ver_1.5.1.tar.gz
shell > mv pg_repack-ver_1.5.1/ pg_repack
shell > cd pg_repack
shell > export PG_CONFIG=/usr/pgsql-16/bin/pg_config
shell > make
shell > make install
##安装扩展
[root@test19-server07 ~]# psql -U postgres -h 127.0.0.1 -p 5432 -W
Password:
psql (16.4)
postgres=# CREATE EXTENSION pg_repack;
CREATE EXTENSION
原理介绍
pg_repack插件支持对全表和索引进行repack操作。
对全表进行repack的实现原理如下:
说明:
pg_repack会在第1、2、6、7步短暂持有原表的排它锁并阻塞读写。其余步骤pg_repack只需要持有原表的ACCESS SHARE锁,不阻塞对原表的INSERT、UPDATE和DELETE操作,但会阻塞DDL操作。
对索引进行repack的实现原理如下:
说明:
pg_repack效果等同于REINDEX CONCURRENTLY,但是比REINDEX CONCURRENTLY更为复杂,如果使用REINDEX CONCURRENTLY,只需要一步就能完成。pg_repack支持该能力的原因是老版本的PostgreSQL不支持REINDEX CONCURRENTLY,从而只能借助pg_repack来实现。
参数详解
通用选项
-a, --all: 重组所有数据库。
-t, --table=TABLE: 仅重组特定表。
-I, --parent-table=TABLE: 重组特定父表及其继承者。
-c, --schema=SCHEMA: 仅重组特定模式中的表。
-s, --tablespace=TBLSPC: 将重组后的表移动到新的表空间。
-S, --moveidx: 将重组后的索引也移动到新的表空间。
-o, --order-by=COLUMNS: 按指定列排序而不是按聚簇键排序。
-n, --no-order: 执行 VACUUM FULL 而不是 CLUSTER。
-N, --dry-run: 显示将要重组的内容,但不执行实际操作。
-j, --jobs=NUM: 为每个表使用指定数量的并行任务。
-i, --index=INDEX仅移动指定的索引。
-x, --only-indexes: 仅移动指定表的索引。
-T, --wait-timeout=SECS: 在冲突时取消其他后端的超时时间。
-D, --no-kill-backend: 超时时不杀死其他后端。
-Z, --no-analyze: 结束时不执行 ANALYZE。
-k, --no-superuser-check: 在客户端跳过超级用户检查。
-C, --exclude-extension: 不重组属于特定扩展的表。
--error-on-invalid-index: 当发现无效索引时不进行重组。
--apply-count: 在回放期间每次事务应用的元组数。
--switch-threshold: 当剩余的元组数达到该阈值时切换表。
连接选项
-d, --dbname=DBNAME: 要连接的数据库名称。
-h, --host=HOSTNAME: 数据库服务器主机或套接字目录。
-p, --port=PORT: 数据库服务器端口。
-U, --username=USERNAME: 连接用户名称。
-w, --no-password: 从不提示输入密码。
-W, --password: 强制提示输入密码。
通用选项
-e, --echo: 回显查询。
-E, --elevel=LEVEL: 设置输出消息级别。
--help: 显示帮助信息,然后退出。
--version: 显示版本信息,然后退出。
Repack普通表和分区表分区
pg_repack支持对普通表或者分区表的某个分区进行repack,其作用类似于CLUSTER或VACUUM FULL操作,清理表中多余的空闲空间,同时重建表上的索引,适用于表空间膨胀的场景。
说明
语法说明一
通过--table参数指定表名,默认情况下效果等同于CLUSTER,repack过程中对之前执行过CLUSTER操作的列进行排序:
/opt/pg_repack/bin/pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --no-superuser-check --echo --table public.saas3
如果希望对指定的列进行排序,可以使用--order-by参数来指定列名:
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --order-by name --no-superuser-check --echo --table public.saas3
postgres=# select * from saas3;
id | name | qq
----+-----------+--------
2 | New Test2 |
4 | New Test4 |
1 | Test1 |
3 | Test3 |
5 | Test3 | qq1223
(5 rows)
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --order-by id --no-superuser-check --echo --table public.saas3
postgres=# select * from saas3;
id | name | qq
----+-----------+--------
1 | Test1 |
2 | New Test2 |
3 | Test3 |
4 | New Test4 |
5 | Test3 | qq1223
(5 rows)
如果不希望进行排序,即希望pg_repack的效果等同于VACUUM FULL,可以使用--no-order参数:
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --no-order --no-superuser-check --echo --table public.saas3
如果数据库集群的CPU和I/O资源充裕,可以使用--jobs参数加速repack操作,它会启动多个进程并发重建索引,适用于表上有多个索引的场景:
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --no-order --no-superuser-check --echo --jobs 3 --table public.saas3
锁冲突时等待最多 30 秒。如果在这 30 秒内锁仍未释放,pg_repack 不会终止其他后端进程,而是放弃重组操作并返回错误
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --no-superuser-check --echo --table public.saas3 --wait-timeout 30 --no-kill-backend
结束时不执行 ANALYZE 操作
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --no-order --no-superuser-check --echo --jobs 3 --parent-table public.saas3 --no-analyze
重组所有数据库
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --no-order --no-superuser-check --echo --jobs 3 --all
Repack分区表和继承表
pg_repack支持对分区表(包括声明式分区表和继承式分区表)进行操作,它会自动找到父表的所有分区,并对每个分区依次进行repack操作。适用于分区表的所有分区都存在空间膨胀的场景。
语法说明二
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --no-order --no-superuser-check --echo --jobs 3 --parent-table public.saas1
说明
Repack索引
pg_repack支持仅对索引进行repack操作,它的作用是重建索引,清理索引中的空闲空间,适用于索引空间膨胀的场景。
说明
语法说明三
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --no-superuser-check --echo --index public.saas3_pkey
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --no-superuser-check --echo --only-indexes --table public.saas3
常见问题
Dry Run
正式执行pg_repack之前建议使用--dry-run选项运行一次,该选项不操作表中的数据,仅验证命令是否合法、流程是否可以跑通。待命令验证成功后,再去掉该选项正式运行pg_repack。
pg_repack -U postgres -h 127.0.0.1 -p 5432 -W -d postgres --no-order --no-superuser-check --echo --jobs 3 --parent-table public.saas3 --dry-run
权限问题
残留对象清理
如果pg_repack在执行过程中异常退出,则repack失败,被repack的表上可能残留了repack过程中创建的对象,需要及时清理,否则可能影响表的使用: