Compaction

更新时间:
复制 MD 格式

当离线导入大量数据或大量执行deleteupdate操作后,可能会由于数据文件的碎片化导致读写性能下降,此时需要执行压缩(Compaction)操作。Compaction操作将多个数据文件合并成一个更大的数据文件,执行Compaction操作有助于重新组织数据存储结构,提高读写效率。本文介绍在Hologres中如何进行Compaction操作。

背景信息

Hologres的数据写入模型使用了与LSM-Tree类似的数据结构,数据都是以Append Only的方式写入存储的。这种数据结构可以将随机写变为顺序写,这是一种面向写优化的数据结构,能够有效提升写入的吞吐量。写入的数据文件需要通过Compaction合并成一个更大的数据文件。

Hologres中存在两类Compaction操作:

  • Auto Compaction

    HologresAuto Compaction是分层的。最多有五层,当单层文件超过五个时,会自动触发Compaction,Compaction完成后的文件会放到下一层。例如Level 0的文件达到五个后,会自动触发Compaction,将五个文件合并,合并后的文件默认最大为64 MB,如果文件大小超过64 MB后,会生成多个文件,合并后的文件会放到Level 1,示意图如下所示:

    image.png

  • 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时会占用大量IOCPU资源,请在写入低峰期执行。一般执行会持续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

参见使用Serverless Computing执行Compaction任务

表级Compaction参数

除手动触发Full Compaction外,Hologres还支持通过表属性(Table Property)对单张表的自动Compaction行为进行精细化调整,包括并发控制、文件选择策略与触发频率等,适用于批量导入前临时暂停Compaction、小文件治理、后台资源争抢处置等场景。

表级参数使用限制

  1. Hologres V4.0及以上版本支持本章节所述的表级Compaction参数。低于V4.0的实例设置这些参数不会生效,请先升级实例。

  2. 本章节所述参数仅对列存表和行列共存表生效,其中行列共存表仅列存部分受这些参数控制。对行存表设置这些参数不会产生效果。

  3. 绝大多数场景下自动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的值后,已在排队的任务会继续执行,但尚未被调度的积压文件不一定会自动重新触发合并,尤其是没有新写入时,建议恢复后手动执行一次VACUUMVACUUM的确切语义请参见使用示例)。

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的文件选择策略和触发频率,与并发参数存在耦合,建议在技术支持指导下使用,处置完成后恢复默认值。

参数

默认值

含义

online_config_partition_table_compaction_semaphore_max

8

逻辑分区表单个调度单元的Compaction并发封顶值,与online_config_compaction_semaphore共同决定实际并发,计算公式请参见核心参数

online_config_parts_to_merge

5

单次Compaction任务最多选取的输入文件数。

online_config_trigger_compaction_picker_threshold

5

候选文件数达到该值才触发一次Compaction,实际生效阈值取该值与online_config_parts_to_merge的较小者。

online_config_orc_max_total_size_to_merge_mb

256

列存表或行列共存表(列存部分)单次Compaction选取文件的总大小上限,单位为MB,间接决定合并产物的文件规模。

online_config_max_total_size_to_merge_mb

512

非列存数据路径单次Compaction选取数据量上限,单位为MB。

online_config_deletion_compaction_ratio

30

文件中被删除行占比超过该百分比时,触发原地合并回收空间。

online_config_ignore_level_compaction

false

选文件时忽略层级约束,允许跨层合并。用于清理每层都有几个小文件但都达不到触发阈值的长尾小文件。

online_config_bottom_level_compaction

true

是否允许最底层文件参与Compaction。

说明

WorkerCompaction总并发(单个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:HologresVACUUM <table_name>的作用是触发该表Flush并等待Compaction任务收敛,是发起一次自动Compaction的手段(尤其在online_config_compaction_semaphore0恢复后,或修改策略参数后),不等价于Full Compaction,不会强制跨层合并所有文件。

注意事项

  1. 参数名拼写不做校验online_config_前缀后接任意名字都能设置成功,SQL不会报错;写错参数名时系统匹配不到对应配置,将静默无效。因此:

    • 参数名请从本文表格中复制,不要手动输入。

    • 设置后应通过hologres.hg_table_properties查询确认已写入。

    • 应通过观测手段(如hologres.hg_table_file_status返回的文件数与文件大小变化)确认行为确实发生了变化,不要仅凭SQL返回成功判断生效。

  2. 物理分区表:对分区父表执行SET_TABLE_PROPERTY不会作用于已存在的分区子表,属性只写入父表自身,而父表不持有数据,因此对存量分区的Compaction行为无实际效果。父表属性只会被之后新建的分区子表在创建时一次性拷贝(含动态分区自动创建的子表),父表后续再修改也不会同步到已建子表。调整分区表的Compaction行为时,应直接对目标分区子表执行SET_TABLE_PROPERTY并逐个核对子表属性;若希望未来新分区默认带上该配置,可同时在父表上设置。

  3. 观测与验收:调优应有观测闭环。可通过SELECT * FROM hologres.hg_table_file_status('<schema_name>.<table_name>'::regclass);实时查看表级文件数与文件大小(逻辑分区表可使用hologres.hg_partition_file_status按分区查看),通过hologres.hg_table_info(每日产出一次)复盘趋势。调优验收的核心判据为:文件总数下降且平均文件大小上升。合并过程中旧文件延迟清理可能造成存储量短时上升,属正常现象。