我正在试验 Apache Iceberg,并试图了解列重命名的工作原理。在我的场景中,我正在使用存储在 AWS S3 中的现有 Parquet 文件数据湖。我的目标是使用现有文件创建 Iceberg 表,而无需移动或重写任何数据。
我能找到的有关列重命名的所有信息似乎都表明它应该可以工作。使用 Iceberg Java SDK:
icebergTable.updateSchema()
.renameColumn("old_name", "new_name")
.commit();
当我执行此操作并查询现有数据(其中列在 Parquet 文件中存储为“old_name”)时,我得到列“new_name”返回的所有空值。我期望原始的“old_name”值映射到“new_name”列。
这个期望有效吗?我是否遗漏了有关 Iceberg 列重命名工作原理的信息?
编辑:附加细节(对于后代 - 我不确定是否有人会对此有答案)
我进一步缩小了问题范围,它似乎仅适用于最初由 Iceberg 以外的其他东西创建的 Parquet 文件中的数据(例如,使用标准 Apache Parquet 库编写的 Parquet 文件)。可以使用 appendFile()
函数将这些文件添加到 Iceberg 表中 (
https://iceberg.apache.org/javadoc/1.6.1/org/apache/iceberg/AppendFiles.html#appendFile(org.apache.iceberg .数据文件))。以这种方式创建的数据,然后附加到 Iceberg 表中,似乎无法正确跟踪列重命名。 有趣的是,最初由 Iceberg 创建的 Parquet 文件也可以以相同的方式附加到另一个 Iceberg 表,并且 that
数据确实正确跟踪列重命名,即使文件被复制和/或移动从它原来的冰山位置。因此,Iceberg 创建的 Parquet 文件似乎有一些独特之处,允许他们跟踪列重命名。
field-id
。
为了支持添加外部创建的 Parquet 文件,Iceberg 提供了在表本身上定义此元数据的功能。这是通过schema.name-mapping.default
属性完成的(此处描述:
https://iceberg.apache.org/spec/#name-mapping-serialization)。听起来这个属性应该在任何时候非 Iceberg Parquet 文件包含在 Iceberg 表中时使用。 具体来说,在本例中,该表是使用以下代码创建的:
val nameMapping = """[
{"field-id": 1, "names": ["old_name"]}
]"""
catalog.buildTable(tableId, schema)
.withPartitionSpec(partitionSpec)
.withProperties(mapOf(TableProperties.DEFAULT_NAME_MAPPING to nameMapping))
.create()
在表上定义这些附加信息后,原来问题中所做的列重命名现在可以工作了。