合并解决哪两个问题
写入频繁的表会积累大量小文件,读取时要打开成百上千个文件,元数据清单也跟着膨胀。合并动作把同一批小文件按目标大小重组成大文件,顺带重写清单文件,让规划阶段少读一些元数据。它不改数据内容,改的是文件布局。
基本信息
| 主要动作 | rewrite_data_files 重写数据文件 |
|---|---|
| 附带动作 | rewrite_manifests 重排清单文件 |
| 目标文件大小 | 常见取 128MB 到 256MB |
| 执行范围 | 按分区或按查询热度挑选 |
| 执行窗口 | 低峰期,避开写入高峰 |
典型使用场景
- 流式落表:每天产生大量小文件,需要定期合并成目标大小
- 历史分区整理:对访问频繁的分区优先处理
- 查询规划变慢:manifest 过多时配合清单重写
- 批量导入之后:导入产生的小文件在空闲时段统一整理
- 容量优化:合并后压缩率通常更好,磁盘占用同步下降
Spark 过程调用示例
Spark 过程调用示例
-- 重写数据文件:合并小文件到目标大小
CALL demo.system.rewrite_data_files(
table => 'db.trade_order',
options => map('target-file-size-bytes', '134217728') -- 128MB
);
-- 重排清单文件:降低元数据解析开销
CALL demo.system.rewrite_manifests(table => 'db.trade_order');
-- 清理孤立文件:窗口要足够长,避免误删提交中的文件
CALL demo.system.remove_orphan_files(
table => 'db.trade_order',
older_than => TIMESTAMP '2026-10-11 00:00:00'
);维护动作对照
| 动作 | 作用 | 执行建议 |
|---|---|---|
| rewrite_data_files | 合并小文件、按大小重组 | 按分区调度,优先热点分区 |
| rewrite_manifests | 重排清单文件 | 与数据重写配套执行 |
| expire_snapshots | 清理过期快照 | 保留足够回溯期后再清理 |
| remove_orphan_files | 删除无主文件 | 时间窗充足,避免误删 |
| 整表重写 | 不推荐作为常规手段 | 成本高、耗时长 |
调度策略怎么定
合并任务最忌讳与写入任务抢资源,也不宜每天全量重写整表。可行做法是按分区维护一张热度表,把最近被查询最多的分区排在最前面,每天只处理固定数量的分区,落在写入低峰时段。这样单次任务的资源消耗可预期,出了问题也容易回退。
孤立文件清理的判定依据是文件是否被任何快照引用且超过指定时间;窗口设得太短,正在提交过程中的临时文件会被误删,导致表出现读取失败。
整表合并任务每月全量跑一次,耗时与资源消耗都难以预估,一旦超时中断还会留下一批半成品文件;按分区增量处理是更稳的选择。