更新时间:2026-07-09 GMT+08:00
分享

使用引擎进行表维护

建议一:定期执行快照过期清理

原因:每次写/更新/删除/Upsert/压缩都会产生新快照,不清理会导致存储持续增长。

实现方式

-- 清理超过7天的快照,保留最近100个
CALL spark_catalog.system.expire_snapshots(
   table => 'db.table',
   older_than => CURRENT_TIMESTAMP - INTERVAL '7' DAYS,
   retain_last => 100,
   stream_results => true
  -- 防止大数据量导致Driver OOM );
  -- 清理特定快照 
CALL spark_catalog.system.expire_snapshots(
   table => 'db.table',
   snapshot_ids => ARRAY(123)
 );
  -- 清理时同时清理未使用的元数据 
CALL spark_catalog.system.expire_snapshots(
   table => 'db.table',
   older_than => TIMESTAMP '2024-01-01 00:00:00',
   clean_expired_metadata => true
 );

注意

  • 分支和标签默认永不过期,需通过表属性history.expire.max-ref-age-ms配置。
  • 建议设置stream_results=>true,避免大数据量时Driver OOM。

Aura实现方式:参考iceberg_expire_snapshots表服务。具体语法请参考:Iceberg表服务函数

建议二:定期清理孤立文件

原因:清理不再被任何元数据文件引用的"孤儿"文件,释放存储空间。

实现方式

-- 先干跑查看待清理文件(推荐生产环境先执行)
CALL spark_catalog.system.remove_orphan_files(
  table => 'db.table',
  dry_run => true
);
-- 实际清理(清理超过7天的孤立文件) 
CALL spark_catalog.system.remove_orphan_files(
  table => 'db.table',
  older_than => CURRENT_TIMESTAMP - INTERVAL '7' DAYS 
);  
-- 清理特定目录下的孤立文件 
CALL spark_catalog.system.remove_orphan_files(
  table => 'db.table',
  location => 'table_location/data'
); 

Aura实现方式参考iceberg_remove_orphanfiles表服务。具体语法请参考:Iceberg表服务函数

建议三:定期执行数据文件压缩

原因:小文件过多会导致大量元数据开销和文件打开成本,影响查询性能。

实现方式

-- 默认binpack策略(合并小文件) 
CALL spark_catalog.system.rewrite_data_files('db.table');  
-- 排序策略(按指定列排序) 
CALL spark_catalog.system.rewrite_data_files(
   table => 'db.table',
   strategy => 'sort',
   sort_order => 'id DESC NULLS LAST, name ASC NULLS FIRST'
 );  
-- Z-Order优化(多列交织排序,提升多列查询性能) 
CALL spark_catalog.system.rewrite_data_files(
   table => 'db.table',
   strategy => 'sort',
   sort_order => 'zorder(c1,c2,c3)'
 );  
-- 启用部分提交和清理dangling deletes 
CALL spark_catalog.system.rewrite_data_files(
   table => 'db.table',
   options => map(
     'min-input-files', '2',
     'remove-dangling-deletes', 'true',
     'partial-progress.enabled', 'true'
   ) 
); 

关键参数

  • target-file-size-bytes: 目标文件大小(默认512MB)
  • min-input-files:触发重写的最小文件数(默认5)
  • rewrite-job-order:排序策略(bytes-asc/desc,files-asc/desc)

Aura实现方式:

Aura中通过OPTIMIZE语法对目标表的指定数据进行重写。

OPTIMIZE table_name REWRITE DATA 
    [ WITH OPTIONS (option_key = option_value [, ...]) ]
    [ WHERE condition ]
    [ ORDER BY target_list [ ASC | DESC ] ]

参数说明:

  • table_name:目标表的名字。取值范围:已存在的表名。
  • condition:一个返回boolean值的表达式,用于判断哪些文件需要被重写。
  • target_list:数据重写的排序键。
  • option_key、option_value:数据重写的配置选项。

建议四:定期重写Manifest文件

原因:优化查询规划性能,manifest中的数据文件按分区规范字段排序。

实现方式

-- 重写manifest 
CALL spark_catalog.system.rewrite_manifests('db.table');  
-- 指定分区规范 
CALL spark_catalog.system.rewrite_manifests(
   table => 'db.table',
   spec_id => 1 
); 

Aura实现方式:参考iceberg_rewrite_manifests表服务。具体语法请参考:Iceberg表服务函数

建议五:定期重写Position Delete文件

原因:压缩小position delete文件,清理dangling deletes(指向已不存在数据文件的删除记录)。

实现方式

-- 压缩并清理dangling deletes 
CALL spark_catalog.system.rewrite_position_delete_files('db.table');  
-- 强制重写所有文件 
CALL spark_catalog.system.rewrite_position_delete_files(
   table => 'db.table',
   options => map('rewrite-all', 'true') 
);

建议六:为重要版本创建标签

原因:便于快速回滚到特定版本,避免误操作后无法恢复。

实现方式

-- 切换到指定快照 
CALL spark_catalog.system.set_current_snapshot(
   table => 'db.table',
   snapshot_id => 123 
);  
-- 切换到标签 
CALL spark_catalog.system.set_current_snapshot(
   table => 'db.table',
   ref => 'my_tag' 
);  
-- 回滚到指定快照 
CALL spark_catalog.system.rollback_to_snapshot('db.table', 1);  
-- 按时间回滚 
CALL spark_catalog.system.rollback_to_timestamp(
   'db.table',
   TIMESTAMP '2024-06-30 00:00:00.000' 
);

Aura实现方式:参考iceberg_set_current_snapshoticeberg_rollback_to_snapshoticeberg_rollback_to_timestamp表服务。具体语法请参考:Iceberg表服务函数

建议七:迁移前使用快照表测试

原因:创建轻量级临时副本用于测试,不影响源表,避免迁移风险。

实现方式

-- 创建快照表 
CALL spark_catalog.system.snapshot('db.source_table', 'db.snapshot_table');  

注意:快照表不是数据文件的唯一所有者,无法执行expire_snapshots物理删除文件。

建议八:正式迁移使用migrate

原因:将现有Hive/Spark表替换为Iceberg表,保留原表作为备份。

实现方式

-- 迁移并添加属性 
CALL spark_catalog.system.migrate(
   'db.old_table',
   map('foo', 'bar') 
);  
-- 不保留备份 
CALL spark_catalog.system.migrate(
   table => 'db.old_table',
   drop_backup => true 
);

建议九:计算表统计信息

原因:收集列的NDV(不同值数量)统计信息,优化查询计划。

实现方式

-- 计算全表统计 
CALL spark_catalog.system.compute_table_stats('db.table');  
-- 指定快照和列 
CALL spark_catalog.system.compute_table_stats(
   table => 'db.table',
   snapshot_id => 'snap1',
   columns => array('col1', 'col2')
);

建议十:计算分区统计信息

原因:增量收集分区统计信息,提升分区裁剪效率。

实现方式

-- 计算分区统计 
CALL spark_catalog.system.compute_partition_stats('db.table');  
-- 指定快照 
CALL spark_catalog.system.compute_partition_stats(
   table => 'db.table',
   snapshot_id => 'snap1' 
);

相关文档