AWS Glue 3.0处理早于1900年时间戳的Parquet文件报错问题
你遇到的报错信息如下:
An error occurred while calling z:org.apache.spark.api.python.PythonRDD.runJob.
You may get a different result due to the upgrading of Spark 3.0: reading dates before 1582-10-15 or timestamps before 1900-01-01T00:00:00Z from Parquet INT96 files can be ambiguous, as the files may be written by Spark 2.x or legacy versions of Hive, which uses a legacy hybrid calendar that is different from Spark 3.0+s Proleptic Gregorian calendar.
See more details in SPARK-31404.
You can set spark.sql.legacy.parquet.int96RebaseModeInRead to 'LEGACY' to rebase the datetime values w.r.t. the calendar difference during reading.
Or set spark.sql.legacy.parquet.int96RebaseModeInRead to 'CORRECTED' to read the datetime values as it is.
以下是可落地的规避方案:
- Reader级别参数配置(优先尝试):无需配置全局Spark参数,直接在读取Parquet的语句中为单reader添加配置项,该配置优先级高于全局配置,不会被Glue强制覆盖。示例代码如下:
Spark原生读接口写法:spark.read.option("parquet.int96RebaseModeInRead", "LEGACY").parquet("s3://你的文件路径/")
Glue DynamicFrame写法:glueContext.create_dynamic_frame.from_options( connection_type = "s3", connection_options = {"paths": ["s3://你的文件路径/"]}, format = "parquet", format_options = {"parquet.int96RebaseModeInRead": "LEGACY"} ) - 读取时字段类型降级后自定义转换:如果上述reader级别配置仍被覆盖,可以在读取时指定INT96时间戳字段的类型为BINARY,后续通过自定义UDF按照LEGACY日历的转换规则将二进制值转为目标时间戳,绕开Spark默认的校验逻辑。
- 存量数据格式预处理:如果数据源可控,可以先使用Glue 2.0对存量Parquet文件做一次格式转换,将INT96类型的时间戳字段统一转为INT64类型的时间戳数值(精度按需选择毫秒/微秒)或者符合ISO标准的字符串格式存储,转换完成后再用Glue 3.0读取新格式的文件即可,不会触发日历校验报错。
- 冷热数据分层处理:如果仅少量冷数据涉及1900年之前的时间戳,可以将数据按时间范围拆分,1900年之前的历史数据继续用Glue 2.0处理,1900年之后的热数据切换为Glue 3.0处理,降低兼容改造的成本。
内容的提问来源于stack exchange,提问作者Robert Kossendey

