PyIceberg结合AWS Glue在S3表中生成冗余嵌套目录问题
我正在使用PyIceberg结合AWS Glue REST目录,向存储在S3中的Iceberg表插入数据。数据插入功能正常,但发现PyIceberg会在实际分区目录前生成多余的嵌套目录。
生成的目录示例:
s3://my-bucket/data/1011/0000/0111/01111110/tenent_id=ten1/account_id=acc7/marketplace_id=UK/time_window_start_year=2021/00000-30-fec66163-f813-4002-acd3-14a59735647b.parquet
期望的目录结构:
s3://my-bucket/data/tenent_id=ten1/account_id=acc7/marketplace_id=UK/time_window_start_year=2021/00000-30.parquet
配置详情:
- 目录类型:AWS Glue REST
- PyIceberg版本:0.9.0
- 存储:S3
- 分区规则:
partition_spec=[ ("tenent_id", "identity"), ("account_id", "identity"), ("marketplace_id", "identity"), ("time_window_start", "year"), ]
- 插入代码片段:
table = catalog.load_table("ams_namespace.ams_poc_table") table.append(pa.Table.from_pylist(fake_data, schema=schema))
技术问询:
- PyIceberg为何会生成这类多余的嵌套目录(如
1011/0000/0111/01111110/)? - 是否可以禁用或控制该行为?
回答
1. 多余嵌套目录的成因
这些嵌套目录是PyIceberg默认生成的分区哈希前缀,是将分区键组合后的哈希值按固定长度拆分生成的层级路径。
在使用REST类目录(如AWS Glue REST)时,Iceberg默认启用该机制,核心目的是:
- 避免S3单目录下文件过多导致的列举、访问性能下降
- 分散存储负载,优化大规模数据场景下的存储效率
2. 禁用或控制该行为的方法
可以通过配置表的写属性来调整该行为,具体有两种操作方式:
方式一:创建表时指定配置
在创建表阶段,添加write.distribution-mode属性并设置为none,即可完全禁用哈希前缀:
from pyiceberg.schema import Schema from pyiceberg.partitioning import PartitionSpec, PartitionField, IdentityTransform, YearTransform # 定义你的表结构 schema = Schema(...) partition_spec = PartitionSpec( PartitionField(source_id=schema.find_field("tenent_id").field_id, transform=IdentityTransform(), name="tenent_id"), PartitionField(source_id=schema.find_field("account_id").field_id, transform=IdentityTransform(), name="account_id"), PartitionField(source_id=schema.find_field("marketplace_id").field_id, transform=IdentityTransform(), name="marketplace_id"), PartitionField(source_id=schema.find_field("time_window_start").field_id, transform=YearTransform(), name="time_window_start_year"), ) # 创建表时禁用哈希前缀 catalog.create_table( "ams_namespace.ams_poc_table", schema=schema, partition_spec=partition_spec, properties={ "write.distribution-mode": "none", "write.format.default": "parquet" } )
方式二:修改已有表的属性
如果表已创建完成,可通过update_properties方法修改配置:
table = catalog.load_table("ams_namespace.ams_poc_table") table.update_properties({"write.distribution-mode": "none"})
如果不想完全禁用,只是调整前缀层级数量,可设置write.partitioning.prefix-length属性:比如设为0是禁用,设为2则生成2层前缀目录。
注意:PyIceberg 0.9.0版本已支持这些配置,AWS Glue作为Iceberg兼容目录可正常适配该设置。
内容的提问来源于stack exchange,提问作者Tharanesh Balaji

