Spark 2.4.x与Spark 3.3.x版本在通用队列的差异对比
DLI整理了Spark2.4.x与Spark 3.3.x版本在通用队列的差异,便于您了解Spark版本升级后通用队列上运行的作业在适配新版本引擎时的影响。
log4j依赖从1.x版本修改为2.x版本
- 说明:
log4j依赖从1.x版本修改为2.x版本
- Spark2.4.x:log4j依赖1.x版本(社区不再支持)。
- Spark 3.3.x:log4j依赖2.x版本。
- 升级引擎版本后是否对作业有影响:
有影响
Spark 3.3.x不支持v1表
- 说明:
Spark2.4.x支持datasourcev1、datasourcev2表。Spark 3.3.x不支持v1表。
具体说明请参考DLI datasourceV1表和datasourceV2表。
- Spark2.4.x:支持datasourcev1、datasourcev2表。
- Spark 3.3.x:不支持支持datasourcev1表。
- 升级引擎版本后是否对作业有影响:
有影响,建议在Spark 2.4.5版本整改到v2表后再升级Spark 3.3.1,具体操作指导可以参考DLI datasourceV1表和datasourceV2表的中的示例。
默认情况下空的input split不创建partition
- 说明:
- Spark2.4.x:默认情况下空的input split将创建partition。
- Spark 3.3.x:默认情况下空的input split不创建partition。
Spark 3.3.x时spark.hadoopRDD.ignoreEmptySplits=true。
- 升级引擎版本后是否对作业有影响:
有影响,需要判断是否使用分区名做业务判断。
eventlog的压缩格式设置为zstd
- 说明:
Spark 3.3.x版本中,spark.eventLog.compression.codec的默认值被设置为zstd,Spark在压缩事件日志时将不再支持使用spark.io.compression.codec的参数值。
- Spark2.4.x:使用spark.io.compression.codec的参数值作为eventlog的压缩格式。
- Spark 3.3.x:spark.eventLog.compression.codec默认设置为zstd。
- 升级引擎版本后是否对作业有影响:
有影响,eventlog的压缩格式发生变化。
spark.launcher.childConectionTimeout修改
- 说明:
- Spark2.4.x:配置名为spark.launcher.childConectionTimeout
- Spark 3.3.x:配置名修改为spark.launcher.childConnectionTimeout
- 升级引擎版本后是否对作业有影响:
有影响,配置参数名称变化。
Spark 3.3.x不再支持将Apache Mesos作为资源管理器
- 说明:
- Spark2.4.x:Spark 2.4.x版本中使用Apache Mesos作为资源管理器。
- Spark 3.3.x:Spark 3.3.x不再支持将Apache Mesos作为资源管理器。
- 升级引擎版本后是否对作业有影响:
功能增强,Spark 2.4.x版本中使用Mesos作为资源管理器,升级到Spark 3.3.x后,你需要考虑切换到其他资源管理器。
Spark 3.3.x会在应用程序自行终止时删除K8s driver
- 说明:Spark 3.3.x会在应用程序自行终止时删除K8s driver。
- 升级引擎版本后是否对作业有影响:
功能增强,升级到Spark 3.3.x后,对于之前依赖于Kubernetes作为资源管理器的作业会有影响。Spark 3.3.x在应用程序终止时会自动删除driver pod可能会影响到作业的资源管理和清理流程。
Spark 3.3.x支持自定义k8s的调度器
- 说明:
- Spark2.4.x:不支持使用指定Kubernetes调度器来管理Spark作业的资源分配和调度。
- Spark 3.3.x:Spark 3.3.x支持自定义k8s的调度器。
- 升级引擎版本后是否对作业有影响:
功能增强,支持自定义调度器管理资源的分配和调度。
Spark将不可为null的模式转换为可空
- 说明:
在Spark 2.4.x版本中,当用户指定的schema包含不可为空的字段时,Spark会将这些不可为null的模式转换为可空的。
但是在Spark 3.3.x版本中,Spark尊重用户指定的schema中的nullability,即如果字段被定义为不可为空,Spark会保持该配置要求,不会自动转换为可空的字段。
- Spark2.4.x:在Spark 2.4.x版本中,当用户指定的schema包含不可为空的字段时,Spark会将这些不可为null的模式转换为可空的。
- Spark 3.3.x:Spark不会自动转换为可空的字段。
如果希望在Spark 3.3.x版本中恢复到Spark 2.4.x版本的执行方式,您可以通过将 spark.sql.legacy.respectNullabilityInTextDatasetConversion设置为true来实现。
- 升级引擎版本后是否对作业有影响:
有影响。
- 示例代码:
执行sql:
spark.read.schema(StructType( StructField("f1", LongType, nullable = false) :: StructField("f2", LongType, nullable = false) :: Nil) ).option("mode", "DROPMALFORMED").json(Seq("""{"f1": 1}""").toDS).show(false);
- Spark 2.4.5
|f1 |f2 | +---+---+ |1 |0 |
- Spark 3.3.1
|f1 |f2 | +---+----+ |1 |null|
- Spark 2.4.5
Spark scala版本变更
- 说明:
Spark scala版本变更。
- Spark2.4.x:Spark scala版本为2.11。
- Spark 3.3.x:Spark scala版本升级到2.12。
- 升级引擎版本后是否对作业有影响:
有影响,jar需要升级scala版本编译。
PySpark支持python版本变更
- 说明:
PySpark支持python版本变更。
- Spark2.4.x:PySpark支持python版本范围2.6+版本到3.7+版本。
- Spark 3.3.x:PySpark支持Python版本范围3.6及以上版本。
- 升级引擎版本后是否对作业有影响:
依赖版本变化,有影响,需要排查是否涉及。
PySpark-pandas支持版本变更
- 说明:
- Spark2.4.x:在Spark 2.4.x版本中,PySpark并没有要求指定Pandas的版本。
- Spark 3.3.x:从Spark 3.3.x版本开始,PySpark需要0.23.2或更高版本的pandas才能使用pandas相关功能,如toPandas、 createDataFrame from pandas DataFrame等。
- 升级引擎版本后是否对作业有影响:
依赖版本变化,有影响,需要排查是否涉及。
PySpark-PyArrow支持版本变更
- 说明:
- Spark2.4.x:在Spark 2.4.x版本中,PySpark并没有要求指定PyArrow的版本。
- Spark 3.3.x:从Spark 3.3.x版本开始,PySpark需要0.12.1或更高版本的PyArrow才能使用PyArrow相关功能,如Pandas_udf、toPandas等。
- 升级引擎版本后是否对作业有影响:
依赖版本变化,有影响,需要排查是否涉及。
以command命名DataFrameWriter触发的查询
在Spark 3.2.x版本中,当DataFrameWriter触发的查询执行被发送给QueryExecutionListener时,这些查询的名称总是被设置为command。而在Spark 3.1及更早版本中,这些查询的名称可能是save、insertInto或saveAsTable之一,这取决于具体的操作。
- 说明:
DataFrameWriter触发的查询执行在发送到QueryExecutionListener时,始终以command命名
- Spark2.4.x:名称为save、insertInto、saveAsTable中的一个
- Spark 3.3.x:command命名
- 升级引擎版本后是否对作业有影响:
有影响
DATE、TIMESTAMP类型字段读取差异
- 说明:
DATE、TIMESTAMP类型字段读取差异,对于Asia/Shanghai时区,时间在1900-01-01 08:05:43之前的值,Spark 2.4.5版本写入后Spark 3.3.1版本读取值与Spark 2.4.5版本读取值不同。
- Spark2.4.x:
以Asia/Shanghai时区的 1900-01-01 00:00:00 为例,通过Spark 2.4.5版本队列写入,Spark 2.4.5版本读取后得到的值为 1900-01-01 00:00:00。
- Spark 3.3.x:
以Asia/Shanghai时区的 1900-01-01 00:00:00 为例,通过Spark 2.4.5版本队列写入,Spark 3.3.1版本配置spark.sql.parquet.int96RebaseModeInRead=LEGACY,读取后得到的值为 1900-01-01 00:00:00,但是配置spark.sql.parquet.int96RebaseModeInRead=CORRECTED时,读取后得到的值为1900-01-01 00:05:43。
- Spark2.4.x:
- 升级引擎版本后是否对作业有影响:
有影响,需要评估DATE、TIMESTAMP类型字段的使用方式。
- 示例代码:
在作业中配置:
spark.sql.session.timeZone=Asia/Shanghai
- Spark 2.4.5
spark.sql("create table parquet_timestamp_test (id int, col0 string, col1 timestamp) using parquet"); spark.sql("insert into parquet_timestamp_test values (1, '245', '1900-01-01 00:00:00')");
执行SQL读取数据:
spark.sql("select * from parquet_timestamp_test").show();
查询结果:
+---+----+-------------------+ | id|col0| col1| +---+----+-------------------+ | 1| 245|1900-01-01 00:00:00| +---+----+-------------------+
- Spark 3.3.1
spark.sql.parquet.int96RebaseModeInRead=LEGACY
执行作业读取数据:
spark.sql("select * from parquet_timestamp_test").show();
查询结果
+---+----+-------------------+ | id|col0| col1| +---+----+-------------------+ | 1| 245|1900-01-01 00:00:00| +---+----+-------------------+
可以再更换配置:
spark.sql.parquet.int96RebaseModeInRead=CORRECTED
并重新执行SQL进行读取:
spark.sql("select * from parquet_timestamp_test").show();
查询结果:
+---+----+-------------------+ | id|col0| col1| +---+----+-------------------+ | 1| 245|1900-01-01 00:05:43| +---+----+-------------------+
- Spark 2.4.5
- 配置项说明:
这些配置项提供了Spark如何处理DATE, TIMESTAMP类型字段中特定的时间(在外推格里历和儒略历之间有争议的时间),例如:对于Asia/Shanghai时区,指的是在1900-01-01 08:05:43之前的值的处理方式。
有歧义的时间:
- 在特定时间之前。例如,对于Asia/Shanghai时区,指的是在1900-01-01 08:05:43之前的值;
- 且数据文件的元数据中未明确标注使用何种历法进行存储的情况。例如,Spark 3.3.x 版本部分情况写入时会在数据文件中记录使用的历法,此时该时间不属于有歧义的时间。
- Datasource parquet表配置项说明
表1 Spark 3.3.1 Datasource parquet表配置项 配置项
默认值
描述
spark.sql.parquet.int96RebaseModeInRead
EXCEPTION (Spark作业默认配置)
读取Parquet文件中INT96类型的TIMESTAMP字段时生效。
- EXCEPTION: 遇到有歧义的时间会抛出报错,读取操作将失败。
- CORRECTED: Spark 不会进行重新调整,而是按照原样读取日期/时间戳。
- LEGACY: Spark 会将日期/时间戳从传统的混合模式(儒略历 + 格里历)日历重新调整到外推格里历。
该配置项仅在 Parquet 文件的写入信息(如 Spark、Hive)未知时才生效。
spark.sql.parquet.int96RebaseModeInWrite
EXCEPTION (Spark作业默认配置)
写入Parquet文件中INT96类型的TIMESTAMP字段时生效。
- EXCEPTION: 遇到有歧义的时间会抛出报错,写入操作将失败
- CORRECTED: Spark 不会进行重新调整,而是按照原样写入日期/时间戳
- LEGACY: 当写入 Parquet 文件时,Spark 会将日期/时间戳从外推格里历重新调整到传统的混合模式(儒略历 + 格里历)。
spark.sql.parquet.datetimeRebaseModeInRead
EXCEPTION (Spark作业默认配置)
读取DATE、TIMESTAMP_MILLIS、TIMESTAMP_MICROS逻辑类型的字段生效。
- EXCEPTION: 遇到有歧义的时间会抛出报错,读取操作将失败。
- CORRECTED: Spark 不会进行重新调整,而是按照原样读取日期/时间戳。
- LEGACY: Spark 会将日期/时间戳从传统的混合模式(儒略历 + 格里历)日历重新调整到外推格里历。
该配置项仅在 Parquet 文件的写入信息(如 Spark、Hive)未知时才生效。
spark.sql.parquet.datetimeRebaseModeInWrite
EXCEPTION (Spark作业默认配置)
写入DATE、TIMESTAMP_MILLIS、TIMESTAMP_MICROS逻辑类型的字段生效。
- EXCEPTION: 遇到有歧义的时间会抛出报错,写入操作将失败
- CORRECTED: Spark 不会进行重新调整,而是按照原样写入日期/时间戳
- LEGACY: 当写入 Parquet 文件时,Spark 会将日期/时间戳从外推格里历重新调整到传统的混合模式(儒略历 + 格里历)。
- Datasource avro表配置项说明
表2 Spark 3.3.1 Datasource avro表配置项 配置项
默认值
描述
spark.sql.avro.datetimeRebaseModeInRead
EXCEPTION (Spark作业默认配置)
读取DATE、TIMESTAMP_MILLIS、TIMESTAMP_MICROS逻辑类型的字段生效。
- EXCEPTION: 遇到有歧义的时间会抛出报错,读取操作将失败。
- CORRECTED: Spark 不会进行重新调整,而是按照原样读取日期/时间戳。
- LEGACY: Spark 会将日期/时间戳从传统的混合模式(儒略历 + 格里历)日历重新调整到外推格里历。
该配置项仅在 Avro 文件的写入信息(如 Spark、Hive)未知时才生效。
spark.sql.avro.datetimeRebaseModeInWrite
EXCEPTION (Spark作业默认配置)
写入DATE、TIMESTAMP_MILLIS、TIMESTAMP_MICROS逻辑类型的字段生效。
- EXCEPTION: 遇到有歧义的时间会抛出报错,写入操作将失败
- CORRECTED: Spark 不会进行重新调整,而是按照原样写入日期/时间戳
- LEGACY: 当写入 Avro 文件时,Spark 会将日期/时间戳从外推格里历重新调整到传统的混合模式(儒略历 + 格里历)。
from_unixtime函数差异
- 说明:
- Spark2.4.x:
以Asia/Shanghai时区的 -2209017600 为例,返回值为1900-01-01 00:00:00。
- Spark 3.3.x:
以Asia/Shanghai时区的 -2209017943 为例,返回值为 1900-01-01 00:00:00。
- Spark2.4.x:
- 升级引擎版本后是否对作业有影响:
有影响,需要检查使用该函数的场景。
- 示例代码:
在作业中配置:
spark.sql.session.timeZone=Asia/Shanghai
- Spark 2.4.5
select from_unixtime(-2209017600);
查询结果:+-----------------------------------------------+ |from_unixtime(-2209017600, yyyy-MM-dd HH:mm:ss)| +-----------------------------------------------+ | 1900-01-01 00:00:00| +-----------------------------------------------+
- Spark 3.3.1
select from_unixtime(-2209017600);
查询结果
+-----------------------------------------------+ |from_unixtime(-2209017600, yyyy-MM-dd HH:mm:ss)| +-----------------------------------------------+ | 1900-01-01 00:05:43| +-----------------------------------------------+
- Spark 2.4.5
unix_timestamp函数差异
- 说明:
对于Asia/Shanghai时区,小于1900-01-01 08:05:43的值。
- Spark2.4.x:
以Asia/Shanghai时区的 1900-01-01 00:00:00 为例,返回值为 -2209017600。
- Spark 3.3.x:
以Asia/Shanghai时区的 1900-01-01 00:00:00 为例,返回值为 -2209017943。
- Spark2.4.x:
- 升级引擎版本后是否对作业有影响:
有影响,需要检查使用该函数的场景。
- 示例代码:
在作业中配置:
spark.sql.session.timeZone=Asia/Shanghai
- Spark 2.4.5
select unix_timestamp('1900-01-01 00:00:00');
查询结果:+--------------------------------------------------------+ |unix_timestamp(1900-01-01 00:00:00, yyyy-MM-dd HH:mm:ss)| +--------------------------------------------------------+ | -2209017600| +--------------------------------------------------------+
- Spark 3.3.1
select unix_timestamp('1900-01-01 00:00:00');
查询结果
+--------------------------------------------------------+ |unix_timestamp(1900-01-01 00:00:00, yyyy-MM-dd HH:mm:ss)| +--------------------------------------------------------+ | -2209017943| +--------------------------------------------------------+
- Spark 2.4.5