Apache Iceberg Compaction 机制详解

涵盖 Spark rewrite_data_files 与 AWS S3 Tables 自动 Compaction | 2026-07

目录
  1. Compaction 概述
  2. rewrite_data_files 核心机制
  3. Bin-Packing 文件筛选逻辑
  4. 场景推演:增量写入后的合并行为
  5. 关键参数详解
  6. Sort 策略 vs Bin-Pack 策略
  7. AWS S3 Tables 自动 Compaction
  8. 最佳实践

1. Compaction 概述

Apache Iceberg 作为一种高性能的表格式(Table Format),支持在对象存储上进行高效的增量写入。但频繁的小文件写入会导致查询性能下降,因此需要 Compaction(文件压缩/合并)来优化数据文件布局。

核心目标:将大量小文件合并为少量大文件,优化查询时的 I/O 效率,同时避免对已经合理大小的文件进行重复操作。

2. rewrite_data_files 核心机制

Spark 通过 Iceberg 的 rewrite_data_files 存储过程来执行 Compaction。默认使用 Bin-Packing 策略。

CALL catalog.system.rewrite_data_files(
  table => 'db.my_table',
  strategy => 'binpack',
  options => map(
    'target-file-size-bytes', '134217728',   -- 128MB
    'min-file-size-bytes',    '100663296',   -- 96MB (75%)
    'max-file-size-bytes',    '241591910'    -- ~230MB (180%)
  )
)

执行流程

扫描所有数据文件
按大小筛选候选文件
Bin-Packing 分组
重写为目标大小文件
提交新 Snapshot

3. Bin-Packing 文件筛选逻辑

Bin-Packing 策略的核心在于只选择"不合理大小"的文件进行重写:

筛选规则

关键结论:已经合并到目标大小范围内的文件,在后续 rewrite_data_files 调用时不会再参与合并

4. 场景推演:增量写入后的合并行为

场景设定

参数
target-file-size-bytes128 MB
min-file-size-bytes (75%)96 MB
max-file-size-bytes (180%)~230 MB

执行过程

Step 1 — 初始状态

10 个文件 × 10MB = 100MB 总数据

所有文件 (10MB) < min (96MB) → 全部选为候选

Step 2 — 第一次合并后

1 个文件 × 100MB(实际合并结果,接近但略小于 target)

100MB 落在 [96MB, 230MB] 范围内 → 标记为"合理大小"

Step 3 — 新增写入

1 × 100MB + 10 × 10MB = 200MB 总数据,11 个文件

Step 4 — 第二次合并

100MB 文件 → 在合理范围内 → ❌ 不参与
10 × 10MB 文件 → 低于 min → ✅ 参与合并
结果:1 × 100MB(原) + 1 × 100MB(新合并) = 2 个文件

5. 关键参数详解

参数 默认值 说明
target-file-size-bytes 512 MB 合并后的目标文件大小
min-file-size-bytes target × 75% 低于此值的文件被视为"太小",参与合并
max-file-size-bytes target × 180% 高于此值的文件被视为"太大",被拆分
min-input-files 5 一个分组至少需要 N 个文件才会触发重写
max-concurrent-file-group-rewrites 5 并行重写的文件组数
partial-progress.enabled false 是否允许部分提交(大表推荐开启)
delete-file-threshold 2147483647 关联 delete file 超过此数的数据文件强制重写

6. Sort 策略 vs Bin-Pack 策略

Bin-Pack

Sort

-- Sort 策略示例
CALL catalog.system.rewrite_data_files(
  table => 'db.my_table',
  strategy => 'sort',
  sort_order => 'event_time ASC NULLS LAST, user_id ASC'
)

7. AWS S3 Tables 自动 Compaction

AWS S3 Tables 提供托管的自动 Compaction 服务,无需用户手动触发:

配置项默认值说明
策略 Bin-Pack 与 Iceberg 社区一致
启用状态 默认开启 表创建后自动生效
目标文件大小 512 MB 可通过 API 调整
调度频率 服务自动管理 无需配置 cron

配置管理 API

aws s3tables put-table-maintenance-configuration \
  --table-bucket-arn arn:aws:s3tables:region:account:bucket/my-bucket \
  --namespace my_namespace \
  --name my_table \
  --type icebergCompaction \
  --value '{
    "status": "enabled",
    "settings": {
      "icebergCompaction": {
        "targetFileSizeBytes": 134217728
      }
    }
  }'

S3 Tables vs 手动 Spark Compaction

S3 Tables 自动 Compaction手动 Spark rewrite_data_files
策略仅 bin-packbin-pack / sort / z-order
频率服务自动调度用户自行触发
可定制性有限(目标大小)完全可配
成本包含在 S3 Tables 费用中需额外 Spark/EMR 集群
适用场景常规小文件合并需要排序优化或精细控制

8. 最佳实践

日常 Compaction 调优建议

  1. 高频 CDC/Upsert 场景:设置 delete-file-threshold=10,每 15-30 分钟执行一次 compaction,防止 delete files 堆积导致 Redshift MaxMessageSize 错误
  2. 大表分区:开启 partial-progress.enabled=true,避免单次事务过大导致冲突
  3. 查询优化:定期(如每周)使用 sort 策略按查询高频列排序,平时使用 binpack
  4. S3 Tables 用户:依赖自动 Compaction 处理常规合并,高频写入场景可调高 compaction 频率
  5. 避免不必要的全量重写:不要将 min-file-size-bytes 设为 target-file-size-bytes,除非明确需要全量重组