【PGCCC】pg_squeeze 1.8:自动表膨胀清理的扩展

PostgreSQL 扩展可从表中删除未使用的空间,并可选择根据特定索引对元组进行排序(就像CLUSTER命令与常规读取/写入同时执行一样)。事实上,我们尝试替换 pg_repack扩展。
虽然提供了非常相似的功能,但pg_squeeze采用了不同的方法:

  1. 纯粹在服务器端实现功能。

  2. 利用 PostgreSQL 数据库服务器的最新改进。

虽然 (1) 使配置和使用都更简单(与使用服务器和客户端代码的pg_repack相比 ),但它还允许使用后台工作者相当顺利地实现无人值守处理。

至于 (2),一个重要的区别(除了使用后台工作者之外)是我们使用逻辑解码而不是触发器来捕获并发变化。


安装

在继续之前安装 PostgreSQL。确保有pg_config二进制文件,这些通常包含在-dev和-devel包中。

git clone  
cd pg_squeeze
make
make install

将这些添加到postgresql.conf:

wal_level = logical
max_replication_slots = 1 # ... or add 1 to the current value.
shared_preload_libraries = 'pg_squeeze' # ... or add the library to the existing ones.

重新启动集群并调用:

CREATE EXTENSION pg_squeeze;

注意:升级安装了 pg_squeeze 的数据库集群时(使用 pg_dumpall/restore 或pg_upgrade),请确保 在升级之前pg_squeeze已安装新集群,否则升级将失败。shared_preload_libraries

常规处理登记表

首先,确保您的表具有主键或唯一约束。这对于处理其他事务在 pg_squeeze执行其工作时可能进行的更改是必要的。

要使pg_squeeze扩展程序了解表,您需要在squeeze.tables表中插入一条记录。一旦添加,就会定期检查表的统计信息。每当表满足“压缩”条件时,就会将“任务”添加到队列中。任务按创建顺序依次处理。

最简单的“注册”如下所示:

INSERT INTO squeeze.tables (tabschema, tabname, schedule)VALUES ('public', 'foo', ('{30}', '{22}', NULL, NULL, '{3, 5}'));

可以选择性地指定附加列,例如:

INSERT INTO squeeze.tables (
    tabschema,
    tabname,
    schedule,
    free_space_extra,
    vacuum_max_age,
    max_retry)VALUES (
    'public',
    'bar',
    ('{30}', '{22}', NULL, NULL, '{3, 5}'),
    30,
    '2 hours',
    2);

以下是表元数据的完整描述。

  • tabschema和tabname分别是模式和表名。

  • schedule列指示何时应检查表,并可能压缩表。计划由以下复合数据类型的值描述,类似于crontab条目:

  • CREATE TYPE schedule AS ( minutes minute[], hours hour[], days_of_month dom[], months month[], days_of_week dow[] );

这里,minutes(0-59)和hours(0-23)指定一天内检查的时间,而days_of_month(1-31)、months(1-12)和 days_of_week(0-7,其中0和7都代表星期日)确定检查的日期。
minute如果、hour和都与当前时间戳匹配,则执行检查month,而 NULL 值分别表示任何分钟、小时和月份。至于days_of_month和days_of_week,其中至少一个需要与当前时间戳匹配,或者两者都需要为 NULL 才能进行检查。
例如,上面的条目表明表public.bar应该每周三和周五的 22:30 检查。

  • ree_space_extraextra free space是触发表处理所需的最小百分比。extra形容词指的是从中获得的可用空间fillfactor不是挤压表的理由。

例如,如果fillfactor等于 60,则在正常运行期间,每页至少应有 40% 保持空闲。如果要确保 70% 的空闲空间使 pg_squeeze 对该表感兴趣,请将其设置 free_space_extra为 30(即所需的 70% 空闲空间减去由于 而产生的 40% 空闲空间fillfactor)。
默认值为free_space_extra50。

  • min_size是表必须占用的最小磁盘空间(以兆字节为单位)才能进行处理。默认值为 8。

  • vacuum_max_age是自上次 VACUUM 完成以来将空闲空间映射 (FSM)视为新鲜的最长时间。一旦此间隔过去,死元组的比例可能会很大,因此需要花费比简单检查 FSM 更多的精力来评估潜在影响pg_squeeze。默认值为 1 小时。

  • max_retry是当相应任务的第一次处理失败时,对表进行压缩的最大额外尝试次数。重试处理的典型原因是在压缩表时表定义发生了更改。如果重试次数达到,则认为表的处理已完成。一旦达到下一个计划时间,就会创建下一个任务。默认值为max_retry0(即不重试)。

  • clustering_index是被处理表的现有索引。处理完成后,表的元组将按照此索引的键进行物理排序。

  • rel_tablespace是应将表移入的现有表空间。NULL 表示表应保留在原处。

  • ind_tablespaces是一个二维数组,每行指定一个索引的表空间映射,第一列和第二列分别表示索引名和表空间名。所有没有指定映射的索引将保留在原表空间中。关于表空间,有一个特殊情况值得一提:如果为表指定了表空间但未为索引指定表空间,则表将移动到该表空间,但索引保留在原始表空间中(即,表的表空间不是索引的默认表空间,正如人们所期望的那样)。

  • skip_analyze表示表处理后不能跟 ANALYZE 命令。默认值为false,表示默认执行 ANALYZE。

  • squeeze.table 是用户唯一需要修改的表。如果您想要更改其他内容,请确保您完全理解自己在做什么。

针对任意表格进行临时处理

还可以手动压缩表格而无需注册(即将相应的记录插入squeeze.tables),并且无需事先检查实际膨胀。

函数签名:

squeeze.squeeze_table(
    tabchema name,
    tabname name,
    clustering_index name,
    rel_tablespace name,
    ind_tablespaces name[])

示例执行:

SELECT squeeze.squeeze_table('public', 'pgbench_accounts');

请注意,该函数不是事务性的:它仅启动后台工作程序,告诉它应处理哪个表并退出。调用该函数的事务的回滚不会恢复工作程序所做的更改。

启用/禁用表处理

要启用膨胀表的处理,请以超级用户身份运行此语句:

SELECT squeeze.start_worker();

该函数启动一个后台工作程序 ( scheduler worker),定期检查哪些已注册的表需要检查膨胀情况,并为每个表创建一个任务。squeeze worker只要特定数据库存在任务,就会启动另一个工作程序 ( )。
如果调度程序工作程序已在当前数据库上运行,则该函数不会报告任何错误,但新的工作程序将立即退出。
如果工作者正在为当前数据库运行,则可以使用以下语句来停止它们:

SELECT squeeze.stop_worker();

只有本文档中提到的函数才被视为用户界面。如果您要调用任何其他函数,请确保您完全理解自己在做什么。

如果希望后台工作者在整个 PostgreSQL 群集启动时自动启动,请将如下条目添加到postgresql.conf文件:

squeeze.worker_autostart = 'my_database your_database'
squeeze.worker_role = postgres


下次启动集群时,将为 启动两个或更多个工作进程(即scheduler worker和 一个或多个), 并且 也为 启动相同的进程。如果采用这种方法,请注意,如果出现以下任一情况,任何工作进程都将拒绝启动或停止而不执行任何工作:squeeze workersmy_databaseyour_database

  1. 扩展pg_squeeze在数据库中不存在,

  2. squeeze.worker_role参数指定不具备超级用户权限的角色。

上面解释的功能/配置变量使用了单数形式worker,尽管实际上有两个工作进程。这是因为在 pg_squeeze 的先前版本中只有一个工作进程,这确保了任务的调度和执行。这种实现更改可能不值得强迫所有用户在升级期间调整其配置文件。

控制对其他后端的影响

尽管大多数时候其他事务都可以对被压缩的表进行读写操作,但需要独占锁才能完成处理。如果 pg_squeeze 偶尔似乎过多地阻止对表的访问,请考虑设置squeeze.max_xlock_timeGUC 参数。例如:

SET squeeze.max_xlock_time TO 100;

告知独占锁的持有时间不应超过 0.1 秒(100 毫秒)。如果最后阶段需要更多时间,pg_squeeze 将释放独占锁,处理其间其他事务提交的更改并再次尝试最后阶段。如果锁定持续时间超出几次,则会报告错误。如果发生这种情况,您应该增加设置或将有问题的表的处理安排到不同的白天,此时写入活动较少。

每个数据库运行多个工作程序

如果您认为单个 squeeze worker 无法应对负载,请考虑将squeeze.workers_per_database配置变量设置为大于 1 的值。这样,pg_squeeze扩展将能够一次处理多个表 - 每个 squeeze worker 处理一个表。但是,请注意,此设置会影响您积极使用 pg_squeeze扩展的所有数据库。集群中所有 squeeze worker 的总数(包括“调度程序 worker”)不能超过核心配置变量max_worker_processes。

监控

  • squeeze.log表中每个成功压缩的表包含一个条目。tabschema和列标识已处理的表。和tabname列说明处理何时开始和结束。是在“初始加载阶段”插入到新表存储中的元组数,即处理开始前表中存在的元组数。另一方面,和 是在表处理期间应用程序插入、更新和删除的元组数。(这些“并发数据更改”也必须合并到压缩表中,否则它们会丢失。)startedfinishedins_initialinsupddel

  • squeeze.errors表包含压缩过程中发生的错误。此处报告的一个常见问题是有人更改了正在处理的表的定义(例如添加或删除了列)。

  • squeeze.get_active_workers()函数返回一个挤压工作者表,这些工作者正在处理当前数据库中的表。该pid列包含工作进程的系统 PID。其他列的含义与表中的对应列相同squeeze.log 。虽然该squeeze.log表仅显示已完成的挤压操作的信息,但该squeeze.get_active_workers()函数可让您检查处理过程中的进度。

取消注册表

如果特定表不再受到定期挤压,只需从squeeze.tables表中删除相应的行。

尽管后台工作者会定期取消注册不存在的表,但取消注册要删除的表也是一个很好的做法。

升级

确保安装 PostgreSQL 和pg_config,请参阅安装 部分。

make # Compile the newer version.
pg_ctl -D /path/to/cluster stop # Stop the cluster.
make install
pg_ctl -D /path/to/cluster start # Start the cluster.

连接到包含的每个数据库pg_squeeze并运行此命令:

ALTER EXTENSION pg_squeeze UPDATE;

从 1.2.x 升级

由于没有直接的方法来自动迁移调度信息(请参阅表格schedule列的注释squeeze.tables ),并且该schedule列不能包含 NULL 值,因此升级会删除squeeze.tables 表格的内容。请在执行升级之前将表格内容导出到文件中,并在升级完成后再次配置这些表格的检查。

并发

  1. 扩展不会阻止其他事务在处理的某些阶段更改表。如果“破坏性命令”(即ALTER TABLE、VACUUMFULL或CLUSTER)TRUNCATE在 squeeze完成之前提交,则该squeeze_table()函数将中止,并且对表所做的所有更改都将回滚。表max_retry的列squeeze.tables决定了 squeeze 工作者将重试多少次。除此之外,更改时间表可能有助于您避免中断。

  2. 与 一样pg_repack,还改变了行的可见性,从而允许mvcc-caveatspg_squeeze第一段中描述的 MVCC 不安全行为。


磁盘空间要求

执行全表压缩需要的可用磁盘空间大约是目标表及其索引的两倍。例如,如果要压缩的表和索引的总大小为 1GB,则需要额外的 2GB 磁盘空间。
#PG证书#PG考试#PostgreSQL培训#PostgreSQL考试#PostgreSQL认证


请使用浏览器的分享功能分享到微信等