IceBerg的自我学习(3)

存储过程

这个IceBerg中非常强大的特性,使用语法为

CALL catalog.system.produce_name( arg_name_2 => arg_2 , arg_name_3 => arg_3)

这是通过名称进行传递参数(推荐),所有的过程都在系统的命名空间中存储

这里我们主要介绍高频使用的存储过程

清理未被元数据引用的孤立文件(remove_orphan_files)

在版本更新的时候,经常会有更新后就不被元数据使用到的文件,这些我们就叫作孤立文件,如果没有被及时清理,这些文件无疑会占用资源,因此该存储过程的适用场景为

  • 定期清理写入失败存储的文件
  • 解决版本更新未被元数据引用的问题
  • 存储优化
  • 解决Spark作业崩溃导致的中间文件残留

先是他的参数说明

CALL catalog.system.remove_orphan_files(
	table => yours_table -- 访问的表(必选)
	,orphan => timestamp -- 时间戳设定(可选),只清除早于该时间戳的孤立文件,要求毫秒级Unix
	,location => custom_path -- 限定查找路径(可选),默认全搜索
	,dry_run => true/false	-- 是否模拟查询结果(可选),true的话返回删除的孤立文件但不实际执行
)

举例使用

-- 安全模式:删除七天前的孤立文件
CALL hive_prod.system.remove_orphan_files(
	table => sales_table
	,orphan => (current_timestamp.cast('long')*1000 - interval 7 days) * 1000
	,dry_run => true
)

-- 实际使用:
CALL hive_prod.system.remove_orphan_files(
	table => sales_table
	,orphan => (current_timestamp - interval 7 days) * 1000
)

使用建议:

  • 窗口时间设置为最近有效的快照时间,避免误删新文件
  • 第一次开启安全模式验证结果
  • 大表的话,可以通过location来限定路径,进行拆分
合并小文件/优化文件分布!!(rewrite_data_files)

这个存储过程主要用来合并小文件,来提升查询效率,因此在存储过程中非常重要

那我们先来看看他的参数

参数分类参数名默认值/规则作用说明
策略控制strategybinpack(默认)或 sort- ‌binpack‌:仅合并文件,不排序。 - ‌sort‌:合并并按指定列排序数据。
排序规则sort_order默认继承表定义- ‌Z-Order‌:zorder(c1,c2) 优化多维查询。 - ‌普通排序‌:c1 ASC NULLS FIRST。
文件筛选where筛选需合并的数据(如 dt='2023-01-01')。
此处下方皆为OPTION选项内填写
目标文件大小target-file-size-bytes512 MB合并后的目标文件大小。
文件合并阈值min-file-size-bytes384 MB(512MB * 75%)小于此值的文件强制合并。
文件拆分阈值max-file-size-bytes921 MB(512MB * 180%)大于此值的文件强制拆分。
文件组数量阈值min-input-files5文件组中文件数超过此值时触发合并。
并发控制max-concurrent-file-group-rewrites5并行处理的最大文件组数。

高级参数调优

参数名作用说明
partial-progress.enabled允许分阶段提交合并结果(避免任务失败全量重试)。
rewrite-job-order控制合并任务执行顺序(按文件大小、数量升序/降序)。
max-file-group-size-bytes单文件组最大处理数据量(默认 100GB),避免大分区资源不足。
remove-dangling-deletes清理无效的 Delete 文件(需额外提交)。
delete-ratio-threshold仅合并删除比例超过 30% 的文件(优化 Merge-on-Read 性能)。

Sort策略特有参数

参数高频使用场景默认值适用性
compression-factor高压缩率数据写入中(需校准)
shuffle-partitions-per-file大规模数据排序且内存不足时低 (保持默认)
  • 若发现 rewrite_data_files 生成的文件大小与预期不符(如压缩后数据膨胀),优先调整 compression-factor。
  • 若使用 Z-Order 且排序键包含变长列,根据字段实际长度调整 var-length-contribution。

首先是排序规则,涉及到了一个排序策略:Z-order策略

这个主要是将多维的数据拆分为一维数据来映射,在保留原始数据的基础上,能够比传统线性排序更好的优化多维查询

例如:x=3(11), y=5(101) → Z-Address=110111

‌列选择‌:优先选择高基数、高频查询的维度(如用户 ID、事件时间)‌。

‌数据治理‌:定期合并小文件(rewrite_data_files)并清理孤立文件,维持存储效率‌。

‌混合策略‌:结合时间分区(如 dt)与 Z-Order,平衡写入性能与查询效率‌。

适用场景:

  • 适合2~4列高频过滤列的复合查询场景
  • 适合在OLAP场景下对多维度等值查询的优化
  • 当数据均匀的时候,Z-order排序的效率显著优于简单排序

要注意Z-Order重写需要额外的资源,因此最好是低频更新的表

使用例子:

-- 基础配置

CALL catalog.system.rewrite_data_files(
  table => 'db.orders',
  options => map(
    'target-file-size-bytes' , '1073741824'  -- 合并为1GB的文件
    ,'min-file-size-bytes','268435456' --256MB以下的文件强制合并
  )
)

-- 排序合并(优化性能)

CALL catalog.system.rewrite_data_files(
  table => 'db.logs',
  stragery => 'sort',
  sort_order => 'zorder(user_id,event_time)', --以z-order的排序来提高性能
  options => map(
    'target-file-size-bytes','2147483648' -- 合并成2GB的文件
    ,'max-concurrent-file-group-rewrites',
    '10' --提高并行度
  )
)

-- 局部合并(分区优化)

CALL catalog.system.rewrite_data_files(
  table => 'db.sales',
  where => 'dt >= "2023-01-01" AND dt <= "2023-01-07"',  -- 合并指定分区
  options => map('rewrite-all', 'true')                   -- 忽略阈值强制合并
);
  • sort策略需要消耗额外资源,因此最好在低负载的时候去使用
  • 如果大分区,就需要调整max-file-group-size-bytes,避免OOM

在合并之后,旧的文件就成为了孤立文件,咱们就可以用刚才讲的remove_orphan_files去进行清楚操作

清楚不需要的过期快照以及文件(expire_snapshots)

IceBerg每次在进行插入/更新/删除/修改的操作,都会产生新的快照,同时保留旧数据以供时间旅行的实现

expire_snapshots就是用来清理这些旧快照以及被这些旧快照单独引用的数据文件,但是仅删除未被其他快照/标签引用的

介绍一下参数

参数名必填类型默认值/行为
table✔️string目标表名(格式:catalog.db.table)。
older_thantimestamp删除早于此时间戳的快照(默认:5天前)。
retain_lastint保留最近的 N个快照(即使早于 older_than,默认 1)。
max_concurrent_deletesint删除文件的并发线程数(默认无并发,单线程执行)。
stream_resultsboolean是否分批次流式传输删除文件到 Spark Driver(默认 false,建议大数据量设为 true 避免 OOM)。
snapshot_idsarray<long>直接指定要删除的快照 ID 列表(需确保非当前快照且未被引用)。
delete_orphan_filesbollean是否同时清理未被任何快照引用的孤立文件,默认为false
file_scan_task_manifestsboolean是否扫描清单文件以验证数据是否被引用,默认为true

光看不行,还得有点操作步骤

-- 删除7天前的快照但是保留十个快照
CALL catalog.system.expire_snapshots(
	table => 'db.sample',
  	older_than => current_timestamp() - INTERVAL '7' DAY,
  	retain_last => 10
);

-- 安全清理示例(含孤立文件清理)
CALL catalog.system.expire_snapshots(
  table => 'db.audit_log',
  older_than => TIMESTAMP '2025-05-09 00:00:00',
  retain_last => 5,
  max_concurrent_deletes => 4,
  stream_results => true,
  delete_orphan_files => true
);

-- 清理旧元数据文件(需单独执行)
CALL catalog.system.remove_old_metadata(
  table => 'db.audit_log',
  older_than => TIMESTAMP '2025-01-01'
);

执行顺序:最好是在rewrite_data_files合并小文件后再执行,清理旧快照

  • 并发删除数 (max_concurrent_deletes) 建议设为集群可用核数的 1/4
合并清单文件以提高元数据查询效率(merge_manifests)

这个主要是用来合并清单文件,使用的程度并不会像合并数据文件一样那么高

可选的参数有

参数名类型作用
rewrite_all boolean控制是否重写所有清单文件而不仅仅是小的清单文件,但是开启了代表消耗更多的资源(默认false)
use_cachingboolean是否使用缓存来加速合并过程,推荐资源充足的时候开启(默认为true)
max_manifests_size_bytesint指定合并后的清单文件大小(默认大小为8MB,大集群建议为32MB)
min_manifests_countint触发合并的最小文件数,建议为5~10避免高频合并

适用场景:

  • 表经过大量的小文件写入操作后,可以合并一下清单文件提高元数据查询效率
  • 读取元数据成为性能瓶颈的时候,可以合并一下
  • 每日ETL后,可以作为维护表的一部分执行
-- 合并特定表的清单文件
CALL system.merge_manifests(
  table => 'hive_prod.analytics.events'
);

-- 强制重写所有清单文件
CALL system.merge_manifests(
  table => 'hive_prod.analytics.events',
  rewrite_all => true
);

-- 带完整参数的合并示例
CALL system.merge_manifests(
  table => 'hive_prod.analytics.events',
  rewrite_all => false,
  max_manifest_size_bytes => 16777216,  -- 16MB
  min_manifest_count => 5
);

但是要注意,合并会导致新的快照出现,历史快照并不会删除,如果要删除还需要配合expire_snapshots

优化合并删除文件(rewrite_position_delete_files)

针对删除文件,可以使用这个存储过程,去合并小位置删除文件,同时移除指向已失效数据文件的删除文件

核心参数有:

参数分类参数名默认值核心作用
并发控制max-concurrent-file-group-rewrites5控制同时重写的文件组数量,优化资源利用率(如内存、CPU)。
文件组拆分max-file-group-size-bytes100GB限制单个文件组处理的数据量,避免大分区导致资源耗尽。
进度管理partial-progress.enabledfalse允许分批提交结果,提升大规模数据重写的容错性。
文件大小策略target-file-size-bytes64MB设定输出文件的理想大小,平衡存储效率与查询性能。
min-file-size-bytes48MB (75%目标值)低于此值的文件强制合并,减少碎片。
max-file-size-bytes115MB (180%目标值)高于此值的文件强制拆分,避免超大文件。
重写优先级rewrite-job-ordernone控制文件组处理顺序: • bytes-asc/desc:按大小排序 • files-asc/desc:按文件数排序 • rewrite-ts-asc/desc : 按时间排序
强制重写rewrite-allfalse忽略其他条件,强制重写所有文件(慎用)。

这是执行的流程

1.根据表元数据的内容定位到所有位置删除文件(以.delete结尾的文件)
2.根据文件大小策略去进行拆分或合并,会跳过指向已失效数据文件的删除文件
3.并行处理,根据并发控制去生成合并文件
4。元数据更新,更新Manifestes和快照文件,旧的快照要配合expire_snapshots删除
-- 带合并示例
CALL system.rewrite_position_delete_files(
  table => 'hive_prod.analytics.events',
  options => map(
    'max-concurrent-file-group-rewrites', '10',
    'target-file-size-bytes', '67108864',  -- 64MB
    'partial-progress.enabled', 'true',
    'rewrite-job-order', 'bytes-desc'
  )
);

迁移数据格式(migrate_table)

将Hive数据格式迁移为IceBerg的表格式,适合在企业技术架构转型的时候去使用

在这个之上,还有一个迁移方式,是migrate,二者的区别是,migrate适合大规模表格式的迁移,migrate_table则是专注于一个表

适合先用migrate进行大规模迁移,再用migrate_table单独优化个别表

捕获数据更新,IceBerg的CDC功能(craete_changelog_view)

这个是IceBerg的CDC功能,也就是用于实时捕获数据更新,通过创建一个视图view来跟踪表的数据变更情况

参数名必填类型默认值说明
table✔️string-源表名(需为 Iceberg 表)。
changelog_viewstring-生成的视图名称,若未指定则返回临时视图。
optionsmap-指定快照范围(如 start-snapshot-idend-timestamp)。
net_changesbooleanfalse是否输出净变更(合并多次更新为最终状态)。
compute_updatesboolean自动判断是否计算更新前后的完整行数据(需主键或 identifier_columns)。
identifier_columnsarray表的主键字段指定用于识别行的唯一字段(若无主键需显式设置)

start-snapshot-id / end-snapshot-id:按快照 ID 范围过滤变更。

start-timestamp / end-timestamp:按时间戳范围过滤变更(如 ‘2024-01-01 00:00:00’)。

排除故障时,可以指定特定快照IDend-snapshot-id:包含结束快照 ID,默认为 table 的当前快照。start-snapshot-id:独占的启动快照 ID。如果未提供,它将从表的第一个快照中读取。

例子:

--追踪数据变更情况
CALL create_changelog_view(  
  table => 'db.users',  
  changelog_view => 'user_changes',  
  options => map('start-timestamp', '2024-03-01', 'end-timestamp', '2024-03-31')  
);  

--增量数据同步
-- 获取净变更(仅最终状态)  
CALL create_changelog_view(  
  table => 'db.orders',  
  net_changes => true,  
  identifier_columns => array('order_id')  
);  

--故障恢复和回溯
-- 分析订单表在快照 12345 到 67890 之间的所有更新  
CALL create_changelog_view(  
  table => 'db.orders',  
  options => map('start-snapshot-id', '12345', 'end-snapshot-id', '67890'),  
  compute_updates => true  
);

具体实例场景

-- 假设有一个 Iceberg 表 iceberg_db.orders,记录订单数据(含字段 order_id、amount、status),现需捕获 ‌2024-03-01 至 2024-03-31‌ 期间的所有变更(插入、更新、删除)

-- 创建变更日志视图,包含更新前后的完整行数据  
CALL catalog.system.create_changelog_view(  
  table => 'iceberg_db.orders',  
  changelog_view => 'orders_changelog',  
  options => map(  
    'start-timestamp', '2024-03-01 00:00:00',  
    'end-timestamp', '2024-03-31 23:59:59'  
  ),  
  compute_updates => true,  
  identifier_columns => array('order_id')  
);

执行SELECT * FROM orders_changelog LIMIT 3

_change_type_commit_snapshotorder_idamountstatus
INSERT123456100199.99PAID
UPDATE_BEFORE123457100250.00PENDING
UPDATE_AFTER123457100250.00CANCELLED
统计表中非重复值的统计数据(compute_table_stats)
Argument NameRequiredTypeDescription
table✔️string表的名称
snapshot_idstring用于收集统计信息的快照的 ID
columnsarray用于收集统计信息的列

例子:

CALL catalog_name.system.compute_table_stats('my_table');

CALL catalog_name.system.compute_table_stats(table => 'my_table', snapshot_id => 'snap1' );

CALL catalog_name.system.compute_table_stats(table => 'my_table', snapshot_id => 'snap1', columns => array('col1', 'col2'));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值