当离线导入大量数据或大量执行delete、update操作后,可能会由于数据文件的碎片化导致读写性能下降,此时需要执行压缩(Compaction)操作。Compaction操作将多个数据文件合并成一个更大的数据文件,执行Compaction操作有助于重新组织数据存储结构,提高读写效率。本文介绍在Hologres中如何进行Compaction操作。
背景信息
Hologres的数据写入模型使用了与LSM-Tree类似的数据结构,数据都是以Append Only的方式写入存储的。这种数据结构可以将随机写变为顺序写,这是一种面向写优化的数据结构,能够有效提升写入的吞吐量。写入的数据文件需要通过Compaction合并成一个更大的数据文件。
Hologres中存在两类Compaction操作:
Auto Compaction
Hologres的Auto Compaction是分层的。最多有五层,当单层文件超过五个时,会自动触发Compaction,Compaction完成后的文件会放到下一层。例如Level 0的文件达到五个后,会自动触发Compaction,将五个文件合并,合并后的文件默认最大为64 MB,如果文件大小超过64 MB后,会生成多个文件,合并后的文件会放到Level 1,示意图如下所示:

Full Compaction
Auto Compaction只会发生在某层内部,不会跨层合并文件。Full Compaction会将所有层的所有文件进行合并,合并后每个文件默认的最大的大小为64 MB,合并后的文件会放到最后一层。
使用限制
仅Hologres V2.1及以上版本支持手动触发Full Compaction,如果您的实例是V2.1以下版本,请您使用自助升级或加入实时数仓Hologres交流群申请升级实例,详情请参见如何获取更多的在线支持?
仅列存表和行列共存表可以主动触发Full Compaction。
行列共存表执行Full Compaction之后,仅列存部分会执行Full Compaction。
使用说明
使用场景:
对于如下场景可以主动触发Full Compaction,合并小文件,提升查询效率:
离线导入大量数据后。
大量执行
delete或者update操作之后。
说明Full Compaction时会占用大量IO和CPU资源,请在写入低峰期执行。一般执行会持续10分钟以上。
命令语法:
SELECT hologres.hg_full_compact_table( '<schema_name.table_name>' [,'max_file_size_mb=<value>'] );参数说明:
参数名称
说明
是否必填
默认值
schema_name.table_name
需要执行Full Compaction操作的表名称。
是
无
max_file_size_mb
(不推荐随意更改)指定需要执行Full Compaction后生成文件大小的最大值,取值必须是正整数,单位为
MB。若调小此参数值,会导致数据文件变多,文件过多会导致查询变慢。
否
64
使用示例:
对表
public.lineitem执行Full Compaction操作:SELECT hologres.hg_full_compact_table( 'public.lineitem');对表
public.lineitem执行Full Compaction操作,指定合并后输出的文件大小最大为256 MB:SELECT hologres.hg_full_compact_table( 'public.lineitem', 'max_file_size_mb=256' );
使用Serverless Computing执行Compaction
表级Compaction参数
除手动触发Full Compaction外,Hologres还支持通过表属性(Table Property)对单张表的自动Compaction行为进行精细化调整,包括并发控制、文件选择策略与触发频率等,适用于批量导入前临时暂停Compaction、小文件治理、后台资源争抢处置等场景。
表级参数使用限制
仅Hologres V4.0及以上版本支持本章节所述的表级Compaction参数。低于V4.0的实例设置这些参数不会生效,请先升级实例。
本章节所述参数仅对列存表和行列共存表生效,其中行列共存表仅列存部分受这些参数控制。对行存表设置这些参数不会产生效果。
绝大多数场景下自动Compaction无需人工干预。除核心参数
online_config_compaction_semaphore外,其余进阶参数与并发参数存在耦合,建议在技术支持指导下用于特定问题的定向处置,处置完成后恢复默认值。
参数设置方式
表级Compaction参数通过SET_TABLE_PROPERTY设置,参数名统一带online_config_前缀,值统一为字符串。设置后对后续调度的Compaction任务生效,运行中的任务不受影响,无需重启实例或重建表。
-- 语法
CALL SET_TABLE_PROPERTY('<schema_name>.<table_name>', 'online_config_<property_name>', '<value>');
-- 示例:将表public.orders的Compaction并发临时设置为0(暂停调度新任务)
CALL SET_TABLE_PROPERTY('public.orders', 'online_config_compaction_semaphore', '0');恢复默认(reset)
值reset表示删除该表级覆盖值,恢复为实例默认行为。
CALL SET_TABLE_PROPERTY('public.orders', 'online_config_compaction_semaphore', 'reset');如果调整前该表已经存在一个业务上需要的覆盖值(例如之前特意设置过4),恢复时应写回原值而不是reset。调整前请先查询并保存原状态,详情请参见查询当前设置。
查询当前设置
SELECT property_key, property_value
FROM hologres.hg_table_properties
WHERE table_namespace = '<schema_name>'
AND table_name = '<table_name>'
AND property_key LIKE 'online_config_%';查询结果为空表示该表没有任何表级覆盖值,使用实例默认行为。
核心参数
online_config_compaction_semaphore
该参数是日常调优的首选参数,控制表的每个数据分片(Tablet)的Compaction并发上限,而不是整张表的总并发。每个数据分片即Compaction的一个调度单元,两者在本文中指同一对象。一张表在每个Shard上通常有一个或多个分片,例如行列共存表的行存、列存部分是各自独立的分片,因此整表理论并发上限约为分片总数 × 该参数值,实际还会受Worker级总并发和资源余量限制。
取值 | 含义 | 适用场景 |
0 | 暂停该表新的Compaction任务。 | 大批量导入前的临时窗口(用完必须恢复)。 |
1 | 最低限度保留合并能力。 | Compaction明显影响在线业务时降载。 |
2 | 默认值。 | 绝大多数场景。 |
3~8 | 提高合并吞吐。 | 文件持续积压且实例资源有余量时,每次加1,小步调整。 |
设置为0的确切语义
阻止该表新的Compaction任务执行。
不会取消已经在运行的任务,已运行任务会自然执行完毕。
该表已被选出、等待执行的任务仍会占用Worker级总并发额度,因此同时对大量表设置为0会挤占其他表的合并并发。
从0恢复为大于0的值后,已在排队的任务会继续执行,但尚未被调度的积压文件不一定会自动重新触发合并,尤其是没有新写入时,建议恢复后手动执行一次
VACUUM(VACUUM的确切语义请参见使用示例)。
从0恢复并触发积压文件合并的示例如下:
CALL SET_TABLE_PROPERTY('public.orders', 'online_config_compaction_semaphore', '2');
VACUUM public.orders;逻辑分区表说明
逻辑分区表会根据当前活跃分区数适当调大并发,单个调度单元的并发上限为min(online_config_partition_table_compaction_semaphore_max, active_partition_count × online_config_compaction_semaphore),默认封顶为8。其中active_partition_count为当前活跃分区数,由系统在运行时统计得出,不是可设置的表属性。
风险提示
不要长期保持为0:文件数和被删除数据会持续积压,查询性能和存储空间都会恶化,且积压越久恢复后的合并压力越大。
不要批量对大量表设置为0或批量调大:所有表共享Worker级总并发,批量设置为0会让被暂停表的排队任务占住全局并发额度,批量调大则容易造成全局排队和资源冲击。
建议一次只调一张表、一个参数,步长尽可能小,观察一个业务周期后再进行下一步。
进阶参数
以下参数影响Compaction的文件选择策略和触发频率,与并发参数存在耦合,建议在技术支持指导下使用,处置完成后恢复默认值。
参数 | 默认值 | 含义 |
| 8 | 逻辑分区表单个调度单元的Compaction并发封顶值,与 |
| 5 | 单次Compaction任务最多选取的输入文件数。 |
| 5 | 候选文件数达到该值才触发一次Compaction,实际生效阈值取该值与 |
| 256 | 列存表或行列共存表(列存部分)单次Compaction选取文件的总大小上限,单位为MB,间接决定合并产物的文件规模。 |
| 512 | 非列存数据路径单次Compaction选取数据量上限,单位为MB。 |
| 30 | 文件中被删除行占比超过该百分比时,触发原地合并回收空间。 |
| false | 选文件时忽略层级约束,允许跨层合并。用于清理每层都有几个小文件但都达不到触发阈值的长尾小文件。 |
| true | 是否允许最底层文件参与Compaction。 |
Worker级Compaction总并发(单个Worker节点上所有表共享的总并发上限)是实例级配置,不是表属性,无法通过SET_TABLE_PROPERTY调整。确有需要请联系技术支持评估。
使用示例
示例一:大批量导入前暂停Compaction,导入后恢复
-- 1. 记录原状态(结果为空表示原本无覆盖值)
SELECT property_key, property_value FROM hologres.hg_table_properties
WHERE table_namespace = 'public' AND table_name = 'orders'
AND property_key = 'online_config_compaction_semaphore';
-- 2. 暂停新的Compaction任务
CALL SET_TABLE_PROPERTY('public.orders', 'online_config_compaction_semaphore', '0');
-- 3. 执行批量导入(期间观察CPU、IO与导入速度)
-- 4. 恢复:以下两条二选一,按步骤1的查询结果选择
-- 4a. 步骤1结果为空(原本无覆盖值)时执行:
CALL SET_TABLE_PROPERTY('public.orders', 'online_config_compaction_semaphore', 'reset');
-- 4b. 步骤1查到原值时,写回原值(把<original_value>替换为步骤1的property_value):
-- CALL SET_TABLE_PROPERTY('public.orders', 'online_config_compaction_semaphore', '<original_value>');
-- 5. 触发积压文件合并(建议低峰执行)
VACUUM public.orders;以下示例二、示例三涉及进阶参数,建议在技术支持指导下执行,处置完成后恢复默认值。
示例二:长尾小文件清理
适用于每层文件数都小于触发阈值,合计几十个小文件无法合并的场景。
CALL SET_TABLE_PROPERTY('public.orders', 'online_config_ignore_level_compaction', 'true');
VACUUM public.orders;
-- 文件数收敛后务必改回,否则长期写入的表会放大Compaction频率和CPU、IO占用
CALL SET_TABLE_PROPERTY('public.orders', 'online_config_ignore_level_compaction', 'reset');示例三:单分片数据量大、文件数多,希望合并成更大的文件
CALL SET_TABLE_PROPERTY('public.orders', 'online_config_orc_max_total_size_to_merge_mb', '512');
VACUUM public.orders;
-- 文件数收敛后恢复默认值
CALL SET_TABLE_PROPERTY('public.orders', 'online_config_orc_max_total_size_to_merge_mb', 'reset');关于VACUUM:Hologres中VACUUM <table_name>的作用是触发该表Flush并等待Compaction任务收敛,是发起一次自动Compaction的手段(尤其在online_config_compaction_semaphore从0恢复后,或修改策略参数后),不等价于Full Compaction,不会强制跨层合并所有文件。
注意事项
参数名拼写不做校验:
online_config_前缀后接任意名字都能设置成功,SQL不会报错;写错参数名时系统匹配不到对应配置,将静默无效。因此:参数名请从本文表格中复制,不要手动输入。
设置后应通过
hologres.hg_table_properties查询确认已写入。应通过观测手段(如
hologres.hg_table_file_status返回的文件数与文件大小变化)确认行为确实发生了变化,不要仅凭SQL返回成功判断生效。
物理分区表:对分区父表执行
SET_TABLE_PROPERTY不会作用于已存在的分区子表,属性只写入父表自身,而父表不持有数据,因此对存量分区的Compaction行为无实际效果。父表属性只会被之后新建的分区子表在创建时一次性拷贝(含动态分区自动创建的子表),父表后续再修改也不会同步到已建子表。调整分区表的Compaction行为时,应直接对目标分区子表执行SET_TABLE_PROPERTY并逐个核对子表属性;若希望未来新分区默认带上该配置,可同时在父表上设置。观测与验收:调优应有观测闭环。可通过
SELECT * FROM hologres.hg_table_file_status('<schema_name>.<table_name>'::regclass);实时查看表级文件数与文件大小(逻辑分区表可使用hologres.hg_partition_file_status按分区查看),通过hologres.hg_table_info(每日产出一次)复盘趋势。调优验收的核心判据为:文件总数下降且平均文件大小上升。合并过程中旧文件延迟清理可能造成存储量短时上升,属正常现象。