case when length(update_timestamp) = 0 or update_timestamp is null or update_timestamp = '' then '2000-01-01 00:00:00' else update_timestamp end as update_timestamp
In Spark 3.0, SHOW CREATE TABLE always returns Spark DDL, even when the given table is a Hive SerDe table. For generating Hive DDL, use SHOW CREATE TABLE AS SERDE command instead.
caused by: 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 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.datetimeRebaseModeInRead to 'LEGACY' to rebase the datetime values w.r.t. the calendar difference during reading. Or set spark.sql.legacy.parquet.datetimeRebaseModeInRead to 'CORRECTED' to read the datetime values as it is.
时间格式导致date_fromat语法不兼容
select DATE_FORMAT(create_time,'Y-M') as create_time,count(*) from t group by DATE_FORMAT(create_time,'Y-M')
和上述问题类似,也是先将行为兼容,保证上线后不报错,然后推动用户再改
caused by: You may get a different result due to the upgrading of Spark 3.0: Fail to recognize 'Y-M' pattern in the DateTimeFormatter.
1) You can set spark.sql.legacy.timeParserPolicy to LEGACY to restore the behavior before Spark 3.0.
2) You can form a valid datetime pattern with the guide from https://spark.apache.org/docs/latest/sql-ref-datetime-pattern.html
spark3升级过程
最近在持续推进着spark3的升级,这里说一下到目前为止发现的问题,以及我这里总结的一些升级建议。
本文分成两个部分,一部分是展示下我们的升级利器-流量校验平台,另一块是我们在从spark2.4到spark3升级过程中发现的一些问题
流量校验平台
我们从2018年开始就搭建了一套用于升级校验的流量校验平台,帮助我们团队应对了多次的版本升级和内部引擎重构
这是流量校验平台的大致架构 我们会在线上部署两个环境,一个是生产环境,跑着现在的稳定版本,另一个是我们经过单测和集成测试后,待发布的新版本引擎,都部署在线上可以让我们不用担心beta版本无法访问线上数据
流量校验程序将不断抽取线上成功运行的流量,然后通过sql改写,改成将数据落到线上的影子库,将改写的sql的发送给beta环境,等待任务执行,将结果记录到db中 然后在现有的可视化平台上配置出任务执行的报表,管理员每天花一些时间解决下发现问题,持续推动升级工作的进行
升级过程中遇到的一些问题
升级过程中遇到的问题很多在官方升级指南中都有说明,这里再稍微提一下,其他小伙伴升级过程中还是要仔细阅读官方的升级指南
这里举一个例子,例子里当update_timestamp是空的时候,用户会给一个写死的值,否则取数据里的update_timestamp
这个sql在spark3默认会报错
问题也比较好跟踪,源代码主要在
org.apache.spark.sql.catalyst.expressions.Cast
中我们需要将
spark.sql.storeAssignmentPolicy
暂时设置成LEGACY
来暂时绕过问题spark3中
hive serDe
的表也会返回spark的ddl,导致结果不一致这里放一下官方原文
不过这个基本都是用户的临时查询,所以影响不大
由于使用java8的时间api导致一些老数据不能读取的问题,暂时将
spark.sql.legacy.parquet/avro.datetimeRebaseModeInRead"
设置成LEGACY
和上述问题类似,也是先将行为兼容,保证上线后不报错,然后推动用户再改
其他问题建议大家仔细阅读升级指南