本文为您介绍 pg_squeeze 插件的简介及使用方法。
概述
pg_squeeze 是表空间收缩插件,用于回收表中因删除、更新产生的膨胀空间,无需长时间持有锁即可在线重建表。
支持版本
PostgreSQL 版本 | 内核版本 |
PostgreSQL 11 | v11.22_r1.35及以上 |
PostgreSQL 12 | v12.22_r1.37及以上 |
PostgreSQL 13 | v13.22_r1.32及以上 |
PostgreSQL 14 | v14.22_r1.42及以上 |
PostgreSQL 15 | v15.14_r1.27及以上 |
PostgreSQL 16 | v16.10_r1.22及以上 |
PostgreSQL 17 | v17.9_r1.16及以上 |
PostgreSQL 18 | v18.3_r1.6及以上 |
说明:
您可在控制台实例详情页查看当前实例的内核版本,或执行
SHOW tencentdb_version; 查询。插件简介
表在频繁的更新、删除操作后,会产生大量死元组和空闲空间,导致表体积膨胀、查询变慢。pg_squeeze 通过在线重建表的方式回收这些空间,收缩过程中对业务的读写影响较小。
环境准备
加载插件
pg_squeeze 是需要预加载的插件,使用前请先在控制台参数设置的
shared_preload_libraries 参数中勾选 pg_squeeze,保存后重启实例。参数设置方法可参考 设置实例参数。注意:
以下参数需正确配置,否则会导致实例重启失败:
squeeze.worker_autostart:自动启动 worker 的数据库列表,需配置为实例中实际存在的数据库。该参数不能设置为空。squeeze.worker_role:worker 连接数据库使用的角色,需配置为实例中已存在且具备目标表访问权限的角色。该参数不能设置为空。创建扩展
连接到需要使用的数据库,执行以下语句创建扩展:
postgres=> CREATE EXTENSION pg_squeeze;CREATE EXTENSION
说明:
pg_squeeze 的扩展安装在
squeeze 模式下,创建时需要当前数据库的 CREATE 权限,请使用具备建库权限的账号在对应数据库执行。收缩膨胀表
确认表有主键
pg_squeeze 需要依赖主键或唯一索引来定位行,请确认目标表存在主键或唯一索引。
执行收缩
以下示例演示完整的收缩流程。先建表、插入数据,再删除一半制造膨胀:
postgres=> CREATE TABLE bloat_test(id int PRIMARY KEY, data text);CREATE TABLEpostgres=> INSERT INTO bloat_test SELECT i, repeat('x', 200) FROM generate_series(1, 10000) AS i;INSERT 0 10000postgres=> DELETE FROM bloat_test WHERE id % 2 = 0;DELETE 5000postgres=> SELECT pg_size_pretty(pg_total_relation_size('bloat_test')) AS size_after_delete;size_after_delete-------------------2632 kB(1 row)
删除一半数据后,表仍占用2632kB。执行收缩:
postgres=> SELECT squeeze.squeeze_table('public', 'bloat_test');squeeze_table---------------(1 row)postgres=> SELECT pg_size_pretty(pg_total_relation_size('bloat_test')) AS size_after_squeeze;size_after_squeeze--------------------1696 kB(1 row)
收缩后表大小降为1696kB,空间得到回收。
查看表膨胀情况
使用
pgstattuple_approx 函数查看表的膨胀情况:postgres=> SELECT * FROM squeeze.pgstattuple_approx('public.bloat_test');table_len | scanned_percent | approx_tuple_count | approx_tuple_len | approx_tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | approx_free_space | approx_free_percent-----------+-----------------+--------------------+------------------+----------------------+------------------+----------------+--------------------+-------------------+---------------------1212416 | 0 | 5000 | 1185920 | 97.81461148648648 | 0 | 0 | 0 | 26496 | 2.1853885135135136(1 row)
字段说明:
字段 | 说明 |
table_len | 表总大小(字节) |
approx_tuple_count | 有效元组数量 |
dead_tuple_count | 死元组数量 |
approx_free_space | 可回收的空闲空间(字节) |
approx_free_percent | 空闲空间占比 |
收缩后
dead_tuple_count 为0,approx_free_percent 很低,说明膨胀空间已回收。自动收缩配置
pg_squeeze 的后台进程会自动收缩配置的表,完整配置包括两部分:
1. 启动后台 worker:通过
squeeze.worker_autostart 参数指定需要自动清理的数据库,squeeze.worker_role 参数指定 worker 连接数据库使用的角色。这两个参数修改后需重启实例。2. 配置收缩表:在
squeeze.tables 表中添加需要自动收缩的表:postgres=> \\d squeeze.tables
squeeze.tables 表主要字段说明:字段 | 说明 |
tabschema / tabname | 模式名 / 表名 |
min_size | 触发收缩的最小表大小(MB) |
free_space_extra | 空闲空间超过该百分比时触发收缩 |
vacuum_max_age | 判断上次 VACUUM 后空闲空间映射(FSM)是否仍新鲜的最大时长;超过后需重新评估膨胀 |
schedule | 收缩调度配置 |
参数说明
pg_squeeze 的相关参数如下:
参数 | 默认值 | 级别 | 说明 |
squeeze.worker_autostart | 空 | postmaster | 自动启动 worker 的数据库列表(逗号分隔) |
squeeze.worker_role | 空 | postmaster | worker 连接数据库使用的角色 |
squeeze.workers_per_database | 1 | postmaster | 每个数据库的最大 worker 进程数 |
squeeze.wait_lock_time | 1000ms | sighup | 等待锁的最大时间 |
squeeze.max_xlock_time | 0 | userset | 表独占锁的最长时间,0表示不限制 |
squeeze.quick_quit | false | userset | 立即停止当前收缩 |
说明:
常见问题
Q:执行 squeeze_table 时报 has no identity index?
A:pg_squeeze 依赖主键或唯一索引来定位行。请为目标表添加主键或唯一索引后再收缩。
Q:收缩过程中会影响业务读写吗?
A:pg_squeeze 采用在线重建方式,收缩期间表仍可正常读写,仅会在最后切换表时短暂加锁,对业务影响较小。