优化 Iceberg 表:排序、统计与删除向量
在写入 Iceberg 表时对数据进行排序,可以让执行引擎基于清单文件中的最小/最大统计信息跳过不必要的文件。如果不排序,文件中的值范围会重叠,导致即使有严格过滤条件也需要读取所有数据。
创建表并写入时不排序的示例:
spark.sql("""
CREATE TABLE habr.paper.write_ordered (
id INT,
name STRING,
event STRING
)
USING ICEBERG
""")
data = [(i, f"name_{i}", f"event_{i}") for i in range(1, 1000000)]
df = spark.createDataFrame(data, ["id", "name", "event"]).repartition(16)
df.writeTo("habr.paper.write_ordered").append()
查询元数据显示混乱的范围:
| id_min | id_max | file_path |
|--------|--------|-----------|
| 2 | 999994 | ... |
| 43 | 999988 | ... |
使用 id < 100000 的过滤器将读取所有文件。
启用排序:
spark.sql("""
ALTER TABLE habr.paper.write_ordered
WRITE ORDERED BY id
""")
重写后得到顺序范围:
| id_min | id_max | file_path |
|--------|--------|-----------|
| 1 | 196479 | ... |
| 196480 | 395983 | ... |
现在,使用 id < 196470 的过滤器只读取一个文件。
配置列统计收集
Iceberg 默认收集所有列的完整最小/最大/截断统计信息,这会增加写入时间而对查询无益。在典型表中,过滤通常发生在 1-2 列上,其他列的统计信息是不必要的。
具有 10 列的扁平表示例:
spark.sql("""
CREATE TABLE habr.paper.typical_flat_table (
id INT,
name STRING,
col_1 STRING,
col_2 STRING,
col_3 STRING,
col_4 STRING,
col_5 STRING,
col_6 STRING,
col_7 STRING,
col_8 STRING
)
USING ICEBERG
""")
通过 TBLPROPERTIES 配置:
spark.sql("""
ALTER TABLE habr.paper.typical_flat_table SET TBLPROPERTIES (
'write.metadata.metrics.default' = 'counts',
'write.metadata.metrics.column.id' = 'full',
'write.metadata.metrics.column.col_1' = 'none'
)
""")
- default: 'counts' — 所有列仅统计行数
- full: 关键过滤列(如 id)的最小/最大 + 截断统计
- none: 未使用列的统计禁用
这减少了写入开销和元数据量,同时不会丢失关键字段上的数据跳过能力。
MoR 中的向量化删除
在合并读取策略中,读取性能取决于删除应用机制。经典的删除文件需要与数据进行连接。
删除文件的类型:
- 等值删除: 删除规则(在 v3 中已弃用)
- 位置删除: 文件中的行位置
在 Iceberg v3 中,位置删除演变为基于 Puffin 格式的删除向量。删除向量是一个位图掩码,可在一个周期内应用于数据文件。
位置删除示例:
| file_path | pos |
|-----------|-----|
| ...parquet | 873 |
| ...parquet | 230 |
替代连接操作:加载位图 + 逻辑与运算。这可以将高删除率下的 MoR 表读取速度提升 5-10 倍。
删除向量特别适用于:
- 频繁更新的批处理 ETL
- 具有缓慢变化维度的表
- 使用 MoR 的流处理
关键要点
- 在可过滤列上使用 WRITE ORDERED BY 排序,减少分析中可读文件的数量
- 配置 write.metadata.metrics.* 最小化写入开销,同时保留数据跳过功能
- Iceberg v3 中的删除向量取代位置删除,通过位图加速 MoR 读取
- 优化无需更改查询或 ETL 逻辑即可生效
- 效果累积:更少的文件、更少的元数据、降低对象存储负载
— Editorial Team
暂无评论。