第15章:文件清理与维护
导言:垃圾回收的重要性
随着时间推移,Paimon表会积累大量的旧Snapshot、临时文件、孤儿文件 。这些无用数据占用磁盘空间并影响元数据查询性能。本章讲解如何安全高效地清理。
第一部分:Snapshot过期清理
1.1 Snapshot的生命周期
ini
Snapshot 1 (时间: 1:00)
Snapshot 2 (时间: 1:10)
Snapshot 3 (时间: 1:20)
...
Snapshot 100 (时间: 1:59)
配置:snapshot-num-retain-min = 10
清理策略:
├─ 保留最新10个Snapshot
├─ 删除Snapshot 1-90
└─ 自动进行,无需手动干预
配置:
'snapshot-num-retain-min' = '10' # 最少保留10个
'snapshot-num-retain-max' = '20' # 最多保留20个
'snapshot-time-retain' = '7d' # 保留7天内的Snapshot
1.2 Snapshot清理的实现
java
public class ExpireSnapshots {
public void expire() {
List<Long> allSnapshots = snapshotManager.listSnapshotIds();
// 计算要删除的Snapshot ID
long earliestToKeep = allSnapshots.size() - minRetain;
for (long id : allSnapshots) {
if (id < earliestToKeep) {
// 删除Snapshot及其数据文件
snapshotManager.deleteSnapshot(id);
}
}
}
}
第二部分:孤儿文件清理
2.1 什么是孤儿文件
场景1:Compaction异常
├─ 新文件生成
├─ 旧文件应该被删除
└─ 但由于异常,旧文件仍存在
→ 孤儿文件(无Snapshot引用)
场景2:提交失败
├─ 临时文件生成
├─ 提交失败,应该清理
└─ 清理失败,临时文件遗留
→ 孤儿文件
识别方法:
├─ 扫描所有Snapshot
├─ 收集被引用的文件
└─ 磁盘上存在但未被引用 → 孤儿文件
2.2 孤儿文件清理
sql
-- 运行清理任务
CALL clean_orphan_files('table_name');
-- 如果支持参数
CALL clean_orphan_files(
table_name => 'orders',
dry_run => true -- 只报告,不删除
);
预期结果:
清理前:磁盘占用 500GB
清理后:磁盘占用 480GB
释放空间:20GB(孤儿文件)
第三部分:Manifest清理
3.1 Manifest过期
ini
大量Snapshot提交后,会有很多旧Manifest文件:
manifest-v1-0
manifest-v2-0
manifest-v3-0
...
manifest-v100-0
配置自动清理:
'manifest-target-size' = '8MB'
'manifest-merge-min-count' = '30'
系统会:
├─ 定期合并小Manifest
├─ 删除被合并的旧版本
└─ 保持Manifest精简
第四部分:生产级维护计划
4.1 日常维护
yaml
# 每天执行(凌晨2点)
cron: 0 2 * * *
维护任务:
1. Snapshot过期清理
├─ 保留最近7天的Snapshot
└─ 自动执行
2. Manifest合并
├─ 合并积累的小Manifest
└─ 优化元数据查询性能
3. 统计信息更新
├─ 重新计算文件统计
└─ 用于查询优化
4.2 周期性维护
yaml
# 每周执行(周日午夜)
cron: 0 0 * * 0
1. 全量Compaction(可选)
├─ 强制压缩所有Level
└─ 优化文件组织
2. Tag清理
├─ 删除超过30天的自动Tag
└─ 保留重要的手动Tag
3. 完整性检查
├─ 验证文件一致性
└─ 报告异常
第五部分:最佳实践
5.1 安全删除数据
sql
错误做法:
DELETE FROM table WHERE dt < '2024-01-01';
→ 生成DELETE标记,需要Compaction清理
→ 不是真正的磁盘释放
正确做法:
-- 方法1:使用分区过期
ALTER TABLE table SET (
'partition.expiration.time' = '90d'
);
→ 自动删除90天前的分区
→ 磁盘立即释放
-- 方法2:手动删除分区
ALTER TABLE table DROP PARTITION dt='2023-12-01';
→ 立即删除该分区所有文件
→ 磁盘立即释放
5.2 监控磁盘使用
sql
-- 查询磁盘占用
SELECT
SUM(file_size) / 1024 / 1024 / 1024 as size_gb
FROM paimon_files;
-- 分区级别的磁盘占用
SELECT
partition,
SUM(file_size) / 1024 / 1024 as size_mb
FROM paimon_files
GROUP BY partition
ORDER BY size_mb DESC
LIMIT 20;
总结
清理的优先级
P0(立即清理):
└─ 孤儿文件(占用空间但无用)
P1(日常清理):
├─ 过期Snapshot(保留配置时间后删除)
└─ 旧Manifest(合并后删除)
P2(周期清理):
└─ 备份清理(保留的Tag和Branch)
下一章:第16章讲解Flink集成深度解析