文档中心>实践教程>云数据库 PostgreSQL>基于 pg_squeeze 的在线表空间回收

基于 pg_squeeze 的在线表空间回收

最近更新时间:2026-04-14 15:47:51

我的收藏
pg_squeeze 是 PostgreSQL 的在线表压缩扩展,可在不阻塞业务读写的情况下回收膨胀空间。本文为您介绍基于 pg_squeeze 的在线表空间回收的实践教程。

前置条件

PostgreSQL 15+,wal_level logical。
shared_preload_libraries 包含 pg_squeeze。
至少1个可用复制槽,2倍表大小的存储空间。
表必须有主键或唯一约束,无长事务。

安装配置

关键参数

以下参数必须在控制台参数设置页面配置(postmaster 级别,需重启)。不设置时 Worker 默认以 postgres 连接,腾讯云内核已禁用此行为。
squeeze.worker_autostart:自动启动 Worker 的数据库名,空格分隔。
squeeze.worker_role:Worker 使用的角色。

创建扩展

CREATE EXTENSION IF NOT EXISTS pg_squeeze;

GUC 参数详解

参数名
默认值
上下文
说明
squeeze.worker_autostart
postmaster
自动启动 Worker 的数据库列表
squeeze.worker_role
postmaster
Worker 使用的角色
squeeze.workers_per_database
1
postmaster
每库最大 Worker 数[1,8]
squeeze.max_xlock_time
0ms
user
排他锁最大持有时间
squeeze.wait_lock_time
1000ms
sighup
等待锁单次最大时间
squeeze.quick_quit
off
user
立即停止 squeeze
squeeze.allow_superuser
off
sighup
允许超级用户作为 worker_role
squeeze.quick_quit 紧急停止开关:
ALTER SYSTEM SET squeeze.quick_quit = on;
SELECT pg_reload_conf();

使用方式

手动执行

SELECT squeeze.squeeze_table('public', 'table_name', NULL, NULL, NULL);

注册自动调度

INSERT INTO squeeze.tables (tabschema, tabname, schedule, free_space_extra, min_size, vacuum_max_age, max_retry)
VALUES ('public', 'orders',
ROW(ARRAY[30]::squeeze.minute[], ARRAY[2]::squeeze.hour[], NULL, NULL, ARRAY[1,2,3,4,5]::squeeze.dow[])::squeeze.schedule,
30, 8, '1 hour', 2);
启动/停止:
SELECT squeeze.start_worker();
SELECT squeeze.stop_worker();

实战示例

-- 创建测试表并插入50000行
CREATE TABLE squeeze_demo (id SERIAL PRIMARY KEY, data TEXT);
INSERT INTO squeeze_demo (data) SELECT md5(random()::text) || repeat('x', 200) FROM generate_series(1, 50000);
-- 插入后: 15 MB

-- 删除2/3数据制造膨胀
DELETE FROM squeeze_demo WHERE id % 3 != 0;
ANALYZE squeeze_demo;
-- 删除后仍 15 MB, 行数 16666

-- 执行 squeeze
SELECT squeeze.squeeze_table('public', 'squeeze_demo', NULL, NULL, NULL);
-- squeeze后: ~5 MB, 回收约10MB(66%)
阶段
表大小
行数
插入后
15MB
50000
删除2/3后
15MB
16666
squeeze 后
≈5MB
16666
回收约66%浪费空间,全程表可正常读写。

监控运维

-- 压缩日志
SELECT * FROM squeeze.log ORDER BY started DESC LIMIT 10;
-- 错误日志
SELECT * FROM squeeze.errors ORDER BY 1 DESC LIMIT 10;
-- 活跃Worker
SELECT * FROM squeeze.get_active_workers();
-- 已注册表
SELECT * FROM squeeze.tables;
-- 待执行任务
SELECT * FROM squeeze.scheduled_for_now;

关于实践的建议

场景
推荐配置
生产环境
worker_autostart=业务库名, worker_role=postgres_admin
锁时间控制
max_xlock_time=100 (100ms)
安全配置
allow_superuser=off (默认)
并发控制
workers_per_database=1 (默认)
注意:
请注意以下几点:
在业务低峰期执行。
存储空间至少需2倍。
无长事务。
监控 WAL 日志。
避免并行多任务。
分区表逐子表。
保留足够复制槽。

故障排查

Worker 无法启动:请检查 shared_preload_libraries、worker_role 设置、数据库日志。
任务未执行:请检查 squeeze.tables 注册、min_size/free_space_extra 条件。
压缩失败:请查看 squeeze.errors、确认主键、检查长事务和存储空间。