apache / apache/parquet-java

Schema mismatch for reading Avro from parquet file with old schema version?

未关闭
#1,628 5 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
Component: Avro Component: Parquet Priority: Minor Type: bug
主要语言
Java
星标
3.1k
派生
1.6k
平均合并
3 天 12 小时
30 天内合并 PR
33

描述

I ran into what looks like a bug in the Parquet Avro reading code, around trying to read a file written with a previous version of a schema with a new, evolved version of the schema.

I'm using Apache Beam's ParquetIO library, which supports passing in schemas to use for "projection" and I was investigating if that would work for me here. However, it didn't work, complaining that my new reader schema had a field that wasn't in the writer schema.

 

I traced this through to a couple places in the parquet-avro code that don't look right to me:

 

First, in `prepareForRead` here:

The `parquetSchema` var comes from `parquetSchema = readContext.getRequestedSchema();` while the `avroSchema` var comes from the parquet file itself with `avroSchema = new Schema.Parser().parse(keyValueMetaData.get(AVRO_SCHEMA_METADATA_KEY));`

I can verify that `parquetSchema` is the schema I'm requesting it be projected to and that `avroSchema` is the schema from the file, but the naming looks backward, shouldn't `parquetSchema` be the one from the parquet file?

Following the stack down, I was hitting this line: https://github.com/apache/parquet-mr/blob/master/parquet-avro/src/main/java/org/apache/parquet/avro/AvroIndexedRecordConverter.java#L91

here it was failing because the `avroSchema` didn't have a field that was in the `parquetSchema`, with the variables assigned in the same way as above. That's the case I was hoping to use this projection for, though - to get the record read with the new reader schema, using the default value from the new schema for the new field. In fact, the comment on line 101 "store defaults for any new Avro fields from avroSchema that are not in the writer schema (parquetSchema)" suggests that the intent was for this to work, but the actual code has the writer schema in avroSchema and the reader schema in parquetSchema.

(Additionally, I'd want this to support schema evolution both for adding an optional field and also removing an old field - so just flipping the names around would result in this still breaking if the reader schema dropped a field from the writer schema...)

Looking to understand if I'm interpreting this correctly, or if there's another path that's intended to be used.

Thank you!

**Environment**: Linux, Apache Beam 2.28.0, Java 11
**Reporter**: [Philip Wilcox](https://issues.apache.org/jira/secure/ViewProfile.jspa?name=philipwilcox)

**Note**: *This issue was originally created as [PARQUET-2055](https://issues.apache.org/jira/browse/PARQUET-2055). Please see the [migration documentation](https://issues.apache.org/jira/browse/PARQUET-2502) for further details.*

贡献指南

这个仓库没有索引到贡献指南

调研方向

从 parquet-avro/src/main/java/org/apache/parquet/avro/AvroReadSupport.java 中的 prepareForRead 开始,沿着 schema 跟踪到 AvroIndexedRecordConverter.java 约第 91 行的位置。将请求的投影 schema 与文件的 Avro 元数据 schema 进行比较,包括关于默认值的注释。当新增和删除字段的预期 schema 演化行为得到澄清或纠正,并针对报告的 Apache Beam 场景完成验证时,即视为完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
java
领域
data-engineering
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
35/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。