Databricks Runtime 7.x 迁移指南 (EoS)
注意
对此 Databricks Runtime 版本的支持已结束。 有关终止支持日期,请参阅终止支持历史记录。 有关所有受支持的 Databricks Runtime 版本,请参阅 Databricks Runtime 发行说明版本和兼容性。
本指南提供的指导可帮助你将 Azure Databricks 工作负载从基于 Apache Spark 2.4 构建的 Databricks Runtime 6.x 迁移到基于 Spark 3.0 构建的 Databricks Runtime 7.3 LTS (EoS)。
本指南列出了一些 Spark 3.0 行为更改,可能需要相应更新 Azure Databricks 工作负载。 其中一些更改包括完全删除 Python 2 支持、升级到 Scala 2.12、完全支持 JDK 11,以及将日期和时间戳从公历切换到前公历。
本指南是 Databricks Runtime 7.3 LTS (EoS) 迁移指南的配套指南。
Databricks Runtime 7.x 上提供的新功能和改进
有关 Databricks Runtime 7.3 LTS 中包含的新功能、改进和库升级的列表,请参阅比迁移出的 Databricks Runtime 版本高的每个相应版本的发行说明。 支持的 Databricks Runtime 7.x 版本包括:
Databricks Runtime 的维护更新(已存档)中列出了发布后的维护更新。
Databricks Runtime 7.3 LTS 系统环境
- 操作系统:Ubuntu 18.04.5 LTS
- Java:
- 7.3 LTS: Zulu 8.48.0.53-CA-linux64(版本 1.8.0_265-b11)
- Scala:2.12.10
- Python:3.7.5
- R:3.6.3 (2020-02-29)
- Delta Lake 0.7.0
主要 Apache Spark 3.0 行为更改
从 Spark 2.4 到 Spark 3.0 的以下行为更改可能需要在从 Databricks Runtime 6.x 迁移到 Databricks Runtime 7.x 时更新 Azure Databricks 工作负载。
注意
本文提供了重要的 Spark 行为更改列表,可供你在迁移到 Databricks Runtime 7.x 时参考。
核心
- Spark 3.0 中删除了已弃用的累加器 v1。
- 事件日志文件将以 UTF-8 编码形式编写,而 Spark History Server 会以 UTF-8 编码形式重播事件日志文件。 以前的 Spark 将事件日志文件编写为驱动程序 JVM 进程的默认字符集,因此在编码不兼容时需要 Spark 2.x 的 Spark History Server 来读取旧的事件日志文件。
- 使用了用于提取无序块的新协议。 建议在运行 Spark 3.0 应用时升级外部无序服务。 可以通过将配置
spark.shuffle.useOldFetchProtocol
设置为true
来继续使用旧的外部无序服务。 否则,Spark 可能会遇到错误,并收到如下信息:IllegalArgumentException: Unexpected message type: <number>
。
PySpark
- 在 Spark 3.0 中,
Column.getItem
是固定的,因此不会调用Column.apply
。 因此,如果将Column
用作getItem
的参数,则应使用索引运算符。 例如,应将map_col.getItem(col('id'))
替换为map_col[col('id')]
。 - 从 Spark 3.0 开始,在使用 Python 3.6 及更高版本的命名参数进行构造时,
Row
字段名称不再按字母顺序排序,并且字段的顺序将与输入的顺序匹配。 若要在默认情况下启用已排序的字段(如在 Spark 2.4 中),请将执行程序和驱动程序的环境变量PYSPARK_ROW_FIELD_SORTING_ENABLED
均设置为true
。 此环境变量在所有执行程序和驱动程序上必须保持一致。 否则,可能会导致失败或答案不正确。 对于低于 3.6 的 Python 版本,字段名称按字母顺序排序,这是唯一排序方式。 - 已弃用 Python 2 支持 (SPARK-27884)。
结构化流式处理
- 在 Spark 3.0 中,当通过
spark.readStream(...)
使用基于文件的数据源(例如 text、json、csv、parquet 和 orc)时,结构化流式处理会强制将源架构设置为可为 Null。 以前,它在源架构中遵循可为 Null 性;但是,这导致使用 NPE 调试问题变得更棘手。 若要还原以前的行为,请将spark.sql.streaming.fileSource.schema.forceNullable
设置为false
。 - Spark 3.0 修复了流间外部联接的正确性问题,该问题导致状态架构更改。 有关更多详细信息,请参阅 SPARK-26154。 如果从使用流间外部联接的 Spark 2.x 构造的检查点启动查询,Spark 3.0 会导致查询失败。 若要重新计算输出,请丢弃该检查点并重播以前的输入。
- 在 Spark 3.0 中,已删除弃用的类
org.apache.spark.sql.streaming.ProcessingTime
。 请改用org.apache.spark.sql.streaming.Trigger.ProcessingTime
。 同样,删除org.apache.spark.sql.execution.streaming.continuous.ContinuousTrigger
是为了支持Trigger.Continuous
,隐藏org.apache.spark.sql.execution.streaming.OneTimeTrigger
是为了支持Trigger.Once
。 请参阅 SPARK-28199。
SQL、数据集和数据帧
- 在 Spark 3.0 中,将值插入到具有不同数据类型的表列中时,将根据 ANSI SQL 标准执行类型强制转换。 不允许某些不合理的类型转换(例如
string
转换为int
和double
转换为boolean
)。 如果值超出列的数据类型范围,会引发运行时异常。 在 Spark 2.4 及更低版本中,只要类型转换是有效的Cast
,就允许在表插入期间进行类型转换。 将超出范围的值插入整型字段时,将插入该值的低阶位(与 Java/Scala 数值类型强制转换相同)。 例如,如果将 257 插入到字节类型的字段中,结果为 1。 此行为由选项spark.sql.storeAssignmentPolicy
控制,默认值为“ANSI”。 将此选项设置为“Legacy”可还原以前的行为。 - 在 Spark 3.0 中,将字符串值强制转换为整型类型(tinyint、smallint、int 和 bigint)、日期/时间类型(日期、时间戳和间隔)和布尔类型时,会先将前导空格和尾随空格 (<= ACSII 32) 进行剪裁,再转换为这些类型值(例如
cast(' 1\t' as int)
返回1
,cast(' 1\t' as boolean)
返回true
,cast('2019-10-10\t as date)
返回日期值2019-10-10
)。 在 Spark 2.4 及更低版本中,将字符串强制转换为整型和布尔值时,不会裁剪两端的空格,上述结果将为null
,而对于日期/时间,只会删除尾随空格 (= ASCII 32)。 请参阅 https://databricks.com/blog/2020/07/22/a-comprehensive-look-at-dates-and-timestamps-in-apache-spark-3-0.html。 - Spark 3.0 中删除了弃用的方法
SQLContext.createExternalTable
和SparkSession.createExternalTable
,改用替代方法createTable
。 - 在 Spark 3.0 中,配置
spark.sql.crossJoin.enabled
成为内部配置,默认情况下为 true,因此默认情况下 Spark 不会在具有隐式交叉联接的 SQL 上引发异常。 - 在 Spark 3.0 中,我们将剪裁函数的参数顺序从
TRIM(trimStr, str)
反转为TRIM(str, trimStr)
以与其他数据库兼容。 - 在 Spark 2.4 及更低版本中,偶有支持
FROM <table>
或FROM <table> UNION ALL FROM <table>
这类 SQL 查询。 在配置单元样式FROM <table> SELECT <expr>
中,SELECT
子句不可忽略。 Hive 和 Presto 都不支持此语法。 因此,自 Spark 3.0 起,会将这些查询视为无效。 - 自 Spark 3.0 起,不再弃用数据集和数据帧 API
unionAll
。 它是union
的别名。 - 在 Spark 2.4 及更低版本中,JSON 数据源的分析程序将某些数据类型(如
IntegerType
)的空字符串视为 NULL。 对于FloatType
和DoubleType
,它在空字符串上将失败并引发异常。 自 Spark 3.0 起,将禁止使用空字符串,并对除StringType
和BinaryType
以外的数据类型引发异常。 - 自 Spark 3.0 起,
from_json
函数支持两种模式:PERMISSIVE
和FAILFAST
。 可以通过mode
选项设置模式。 默认模式为PERMISSIVE
。 在以前的版本中,from_json
的行为既不符合PERMISSIVE
也不符合FAILFAST,
,特别是在处理格式错误的 JSON 记录时。 例如,架构为a INT
的 JSON 字符串{"a" 1}
由以前的版本转换为null
,但是 Spark 3.0 将其转换为Row(null)
。
DDL 语句
- 在 Spark 3.0 中,没有特定提供程序的
CREATE TABLE
使用spark.sql.sources.default
的值作为其提供程序。 在 Spark 2.4 及更低版本中,该值为 Hive。 若要还原 Spark 3.0 之前的行为,可以将spark.sql.legacy.createHiveTableByDefault.enabled
设置为true
。 - 在 Spark 3.0 中,将值插入到具有不同数据类型的表列中时,将根据 ANSI SQL 标准执行类型强制转换。 不允许某些不合理的类型转换(例如
string
转换为int
和double
转换为boolean
)。 如果值超出列的数据类型范围,会引发运行时异常。 在 Spark 2.4 及更低版本中,只要类型转换是有效的Cast
,就允许在表插入期间进行类型转换。 将超出范围的值插入整型字段时,将插入该值的低阶位(与 Java/Scala 数值类型强制转换相同)。 例如,如果将 257 插入到字节类型的字段中,结果为 1。 此行为由选项spark.sql.storeAssignmentPolicy
控制,默认值为“ANSI”。 将此选项设置为“Legacy”可还原以前的行为。 - 在 Spark 3.0 中,即使给定的表是 Hive SerDe 表,
SHOW CREATE TABLE
也始终返回 SPARK DDL。 若要生成 Hive DDL,请改用SHOW CREATE TABLE AS SERDE
命令。 - 在 Spark 3.0 中,非 Hive-Serde 表中不允许使用
CHAR
类型的列,如果检测到CHAR
类型,则CREATE/ALTER TABLE
命令将失败。 请改用STRING
类型。 在 Spark 2.4 及更低版本中,会将CHAR
类型视为STRING
类型,并忽略长度参数。
UDF 和内置函数
- 在 Spark 3.0 中,默认情况下不允许使用
org.apache.spark.sql.functions.udf(AnyRef, DataType)
。 将spark.sql.legacy.allowUntypedScalaUDF
设置为true
以继续使用。 在 Spark 2.4 及更低版本中,如果org.apache.spark.sql.functions.udf(AnyRef, DataType)
获取了具有基元类型参数的 Scala 闭包,则当输入值为 NULL 时,返回的 UDF 将返回 NULL。 但是,在 Spark 3.0 中,如果输入值为 NULL,则 UDF 将返回 Java 类型的默认值。 例如,如果列 x 为 NULL,则val f = udf((x: Int) => x, IntegerType), f($"x")
在 Spark 2.4 及更低版本中返回 NULL,在 Spark 3.0 中返回 0。 引入此行为变更是因为 Spark 3.0 是默认使用 Scala 2.12 生成的。 - 在 Spark 2.4 及更低版本中,可以通过
CreateMap
、StringToMap
等内置函数来创建具有重复键的映射。具有重复键的映射的行为是不确定的,例如,映射查找会遵循首先出现的重复键,Dataset.collect
仅保留最后出现的重复键,MapKeys
返回重复的键等。在 Spark 3.0 中,发现重复的键时,Spark 会引发RuntimeException
。 可以将spark.sql.mapKeyDedupPolicy
设置为LAST_WIN
以使用最终生效的策略来删除重复的映射键。 用户仍然可以从不强制执行此操作的数据源(例如 Parquet)中读取具有重复键的映射值,该行为是不确定的。
“数据源”
- 在 Spark 2.4 及更低版本中,如果无法将分区列值强制转换为相应的用户提供的架构,则会将其转换为 NULL。 在 3.0 中,将使用用户提供的架构来验证分区列值。 如果验证失败,将引发异常。 可以通过将
spark.sql.sources.validatePartitionColumns
设置为false
来禁用此类验证。 - 在 Spark 2.4 及更低版本中,JSON 数据源的分析程序将某些数据类型(如
IntegerType
)的空字符串视为 NULL。 对于FloatType
、DoubleType
、DateType
和TimestampType
,它在空字符串上将失败并引发异常。 Spark 3.0 禁止使用空字符串,并且将对除StringType
和BinaryType
以外的数据类型引发异常。 可以通过将spark.sql.legacy.json.allowEmptyString.enabled
设置为true
来还原以前允许空字符串的行为。 - 在 Spark 3.0 中,如果文件或子目录在递归目录列表期间消失(即它们出现在中间列表中,但由于并发文件删除或对象存储一致性问题而在递归目录列表的后续阶段无法读取或列出),那么除非
spark.sql.files.ignoreMissingFiles
为true
(默认为 false),否则列表将失败并出现异常。 在以前的版本中,会忽略这些缺少的文件或子目录。 请注意,此行为更改仅适用于初始表文件列表(或REFRESH TABLE
)期间,而不适用于查询执行:净更改是指在表文件列表和查询规划期间遵守spark.sql.files.ignoreMissingFiles
,而不仅仅是在查询执行时遵守。 - 在 Spark 2.4 及更低版本中,CSV 数据源在 PERMISSIVE 模式下会将格式错误的 CSV 字符串转换为全为 NULL 的行。 在 Spark 3.0 中,如果成功分析了某些 CSV 列值并转换为所需类型,则返回的行可能包含非 NULL 字段。
- 在 Spark 3.0 中,保存
TIMESTAMP
列时默认使用 parquet 逻辑类型TIMESTAMP_MICROS
。 在 Spark 2.4 及更低版本中,TIMESTAMP
列另存为 parquet 文件中的INT96
。 请注意,某些 SQL 系统(如 Hive 1.x 和 Impala 2.x)只能读取 INT96 时间戳。 可以将spark.sql.parquet.outputTimestampType
设置为INT96
以还原以前的行为并保持互操作性。 - 在 Spark 3.0 中,当使用用户提供的架构写入 Avro 文件时,字段将按 catalyst 架构和 Avro 架构的字段名称进行匹配,而不是按位置。
查询引擎
- 在 Spark 3.0 中,如果数据集查询包含由自联接引起的不明确的列引用,则该查询将失败。 典型示例:
val df1 = ...; val df2 = df1.filter(...);, then df1.join(df2, df1("a") > df2("a"))
返回令人困惑的空结果。 这是因为 Spark 无法解析指向自联接表的数据集列引用,并且df1("a")
与 Spark 中的df2("a")
完全相同。 若要还原 Spark 3.0 之前的行为,可以将spark.sql.analyzer.failAmbiguousSelfJoin
设置为false
。 - 在 Spark 3.0 中,以科学记数法表示的数字(例如
1E2
)被分析为Double
。 在 Spark 2.4 及更低版本中,它们被分析为Decimal
。 若要还原 Spark 3.0 之前的行为,可以将spark.sql.legacy.exponentLiteralAsDecimal.enabled
设置为true
。 - 在 Spark 3.0 中,配置
spark.sql.crossJoin.enabled
成为内部配置,默认情况下为 true。 默认情况下,Spark 不会在具有隐式交叉联接的 SQL 上引发异常。 - 在 Spark 2.4 及更低版本中,浮点型/双精度浮点型 -0.0 在语义上等于 0.0,但是 -0.0 和 0.0 在聚合分组键、窗口分区键和联接键中使用时被视为不同的值。 Spark 3.0 中修复了此 bug。 例如,
Seq(-0.0, 0.0).toDF("d").groupBy("d").count()
在 Spark 3.0 中返回[(0.0, 2)]
,在 Spark 2.4 及更低版本中返回[(0.0, 1), (-0.0, 1)]
。 - 在 Spark 3.0 中,会使用 SQL 配置
spark.sql.session.timeZone
将TIMESTAMP
文本转换为字符串。 在 Spark 2.4 及更低版本中,该转换使用 Java 虚拟机的默认时区。 - 在 Spark 3.0 中,Spark 在涉及日期/时间戳的二进制比较中将
String
强制转换为Date/Timestamp
。 通过将spark.sql.legacy.typeCoercion.datetimeToString.enabled
设置为true
,可以还原之前将Date/Timestamp
强制转换为String
的行为。 - 在 Spark 2.4 及更低版本中,会以无提示方式忽略无效的时区 ID 并将其替换为 GMT 时区,例如,在
from_utc_timestamp
函数中。 在 Spark 3.0 中,将拒绝此类时区 ID,且 Spark 将引发java.time.DateTimeException
。 - 在 Spark 3.0 中,前公历用于分析、设置格式和转换日期和时间戳,还用于提取如年、日等的子组件。 Spark 3.0 使用基于 ISO 时序的 java.time 包中的 Java 8 API 类。 在 Spark 2.4 及更低版本中,这些操作是使用混合日历(儒略历 + 公历)执行的。 此更改会影响 1582 年 10 月 15 日(公历)之前的日期结果,并影响以下 Spark 3.0 API:
- 时间戳/日期字符串的分析/格式设置。 当使用用户指定的模式进行分析和格式设置时,这会影响 CSV/JSON 数据源以及
unix_timestamp
、date_format
、to_unix_timestamp
、from_unixtime
、to_date
、to_timestamp
函数。 在 Spark 3.0 中,我们在sql-ref-datetime-pattern.md
中定义了自己的模式字符串,该模式字符串是通过后台java.time.format.DateTimeFormatter
实现的。 新的实现对其输入进行严格检查。 例如,如果模式为yyyy-MM-dd
,则无法分析2015-07-22 10:00:00
时间戳,因为分析程序不会使用整个输入。 另一个示例是dd/MM/yyyy hh:mm
模式无法分析31/01/2015 00:00
输入,因为hh
预设小时数在 1-12 范围内。 在 Spark 2.4 及更低版本中,java.text.SimpleDateFormat
用于时间戳/日期字符串转换,受支持的模式在java.text.SimpleDateFormat
中进行了介绍。 可以通过将spark.sql.legacy.timeParserPolicy
设置为LEGACY
来还原旧的行为。 weekofyear
、weekday
、dayofweek
、date_trunc
、from_utc_timestamp
、to_utc_timestamp
和unix_timestamp
函数使用java.time
API 来计算每年的第几周、每周的第几天以及转换自/到 UTC 时区的TimestampType
值。- JDBC 选项
lowerBound
和upperBound
的转换方式与将字符串强制转换为 TimestampType/DateType 值的方式相同。 该转换基于前公历以及 SQL 配置spark.sql.session.timeZone
定义的时区。 在 Spark 2.4 及更低版本中,该转换基于混合日历(儒略历 + 公历)和默认系统时区。 - 对
TIMESTAMP
和DATE
文本进行格式设置。 - 从字符串创建类型为
TIMESTAMP
和DATE
的文本。 在 Spark 3.0 中,通过强制转换为TIMESTAMP/DATE
值将字符串转换为类型为TIMESTAMP/DATE
的文本。 例如,TIMESTAMP '2019-12-23 12:59:30'
在语义上等效于CAST('2019-12-23 12:59:30' AS TIMESTAMP)
。 如果输入字符串不包含有关时区的信息,在这种情况下,将使用 SQL 配置spark.sql.session.timeZone
中的时区。 在 Spark 2.4 及更低版本中,该转换基于 JVM 系统时区。 默认时区的不同源可能会更改类型为TIMESTAMP
和DATE
的文本的行为。
- 时间戳/日期字符串的分析/格式设置。 当使用用户指定的模式进行分析和格式设置时,这会影响 CSV/JSON 数据源以及
Apache Hive
- 在 Spark 3.0 中,我们将内置的 Hive 版本从 1.2 升级到 2.3,这会带来以下影响:
- 可能需要根据要连接的 Hive 元存储的版本设置
spark.sql.hive.metastore.version
和spark.sql.hive.metastore.jars
。 例如,如果 Hive 元存储版本为 1.2.1,则将spark.sql.hive.metastore.version
设置为1.2.1
,将spark.sql.hive.metastore.jars
设置为maven
。 - 需要将自定义 SerDes 迁移到 Hive 2.3 或使用
hive-1.2
配置文件构建自己的 Spark。 有关更多详细信息,请参阅 HIVE-15167。 - 在 SQL 中使用
TRANSFORM
运算符进行脚本转换时,Hive 1.2 和 Hive 2.3 之间的十进制字符串表示形式可能有所不同,具体取决于配置单元的行为。 在 Hive 1.2 中,字符串表示形式会忽略尾随的零。 但是在 Hive 2.3 中,如有必要,它将始终用尾随零填充至 18 位数。 - 在 Databricks Runtime 7.x 中,读取 Hive SerDe 表时,默认情况下 Spark 不允许读取非表分区的子目录下的文件。 若要允许它,请将配置
spark.databricks.io.hive.scanNonpartitionedDirectory.enabled
设置为true
。 这不影响 Spark 原生表读取器和文件读取器。
- 可能需要根据要连接的 Hive 元存储的版本设置
MLlib
OneHotEncoder
(在 2.3 中已弃用)在 3.0 中已删除,OneHotEncoderEstimator
现重命名为OneHotEncoder
。org.apache.spark.ml.image.ImageSchema.readImages
(在 2.3 中已弃用)在 3.0 中已删除。 请改用spark.read.format('image')
。- 具有参数 Int
runs
的org.apache.spark.mllib.clustering.KMeans.train
(在 2.1 中已弃用)在 3.0 中已删除。 使用训练方法而不运行。 org.apache.spark.mllib.classification.LogisticRegressionWithSGD
(在2.0 中已弃用)在 3.0 中已删除,改用org.apache.spark.ml.classification.LogisticRegression
或spark.mllib.classification.LogisticRegressionWithLBFGS
。org.apache.spark.mllib.feature.ChiSqSelectorModel.isSorted
(在 2.1 中已弃用)在 3.0 中已删除,不适用于子类。org.apache.spark.mllib.regression.RidgeRegressionWithSGD
(在 2.0 中已弃用)在 3.0 中已删除。 将org.apache.spark.ml.regression.LinearRegression
与elasticNetParam = 0.0
配合使用。 请注意,RidgeRegressionWithSGD
的默认regParam
为 0.01,而LinearRegression
的默认值为0.0。org.apache.spark.mllib.regression.LassoWithSGD
(在 2.0 中已弃用)在 3.0 中已删除。 将org.apache.spark.ml.regression.LinearRegression
与elasticNetParam = 1.0
配合使用。 请注意,LassoWithSGD
的默认regParam
为 0.01,而LinearRegression
的默认值为0.0。org.apache.spark.mllib.regression.LinearRegressionWithSGD
(在 2.0 中已弃用)在 3.0 中已删除。 请改用org.apache.spark.ml.regression.LinearRegression
或LBFGS
。org.apache.spark.mllib.clustering.KMeans.getRuns
和setRuns
(在 2.1 中已弃用)在 3.0 中已删除,并且自 Spark 2.0.0 起不再起作用。org.apache.spark.ml.LinearSVCModel.setWeightCol
(在 2.4 中已弃用)在 3.0 中已删除,不适用于用户。- 在 3.0 中,
org.apache.spark.ml.classification.MultilayerPerceptronClassificationModel
扩展了MultilayerPerceptronParams
以公开训练参数。 因此,MultilayerPerceptronClassificationModel
中的layers
已从Array[Int]
更改为IntArrayParam
。 应使用MultilayerPerceptronClassificationModel.getLayers
而不是MultilayerPerceptronClassificationModel.layers
来检索层的大小。 org.apache.spark.ml.classification.GBTClassifier.numTrees
(在 2.4.5 中已弃用)在 3.0 中已删除。 请改用getNumTrees
。org.apache.spark.ml.clustering.KMeansModel.computeCost
(在 2.4 中已弃用)在 3.0 中已删除,改用ClusteringEvaluator
。org.apache.spark.mllib.evaluation.MulticlassMetrics
中的成员变量精准率(在 2.0 中已弃用)在 3.0 中已删除。 请改用准确度。org.apache.spark.mllib.evaluation.MulticlassMetrics
中的成员变量召回率(在 2.0 中已弃用)在 3.0 中已删除。 请改用accuracy
。org.apache.spark.mllib.evaluation.MulticlassMetrics
中的成员变量fMeasure
(在 2.0 中已弃用)在 3.0 中已删除。 请改用accuracy
。org.apache.spark.ml.util.GeneralMLWriter.context
(在 2.0 中已弃用)在 3.0 中已删除。 请改用session
。org.apache.spark.ml.util.MLWriter.context
(在 2.0 中已弃用)在 3.0 中已删除。 请改用session
。org.apache.spark.ml.util.MLReader.context
(在 2.0 中已弃用)在 3.0 中已删除。 请改用session
。- 在 3.0 中,
abstract class UnaryTransformer[IN, OUT, T <: UnaryTransformer[IN, OUT, T]]
更改为abstract class UnaryTransformer[IN: TypeTag, OUT: TypeTag, T <: UnaryTransformer[IN, OUT, T]]
。 - 在 Spark 3.0 中,Pyspark 中的多类逻辑回归现在会(正确地)返回
LogisticRegressionSummary
而不是子类BinaryLogisticRegressionSummary
。 在这种情况下,BinaryLogisticRegressionSummary
公开的其他方法仍不起作用。 (SPARK-31681) - 在 Spark 3.0 中,
pyspark.ml.param.shared.Has*
mixin 不再提供任何set*(self, value)
资源库方法,请改用相应的self.set(self.*, value)
。 有关详细信息,请参阅 SPARK-29093。 (SPARK-29093)
其他行为变更
升级到 Scala 2.12 涉及以下更改:
包单元序列化的处理方式不同。 下面的示例演示了行为变更以及如何处理它。
运行以下包单元中定义的
foo.bar.MyObjectInPackageCell.run()
会触发“java.lang.NoClassDefFoundError: Could not initialize class foo.bar.MyObjectInPackageCell$
”错误package foo.bar case class MyIntStruct(int: Int) import org.apache.spark.sql.SparkSession import org.apache.spark.sql.functions._ import org.apache.spark.sql.Column object MyObjectInPackageCell extends Serializable { // Because SparkSession cannot be created in Spark executors, // the following line triggers the error // Could not initialize class foo.bar.MyObjectInPackageCell$ val spark = SparkSession.builder.getOrCreate() def foo: Int => Option[MyIntStruct] = (x: Int) => Some(MyIntStruct(100)) val theUDF = udf(foo) val df = { val myUDFInstance = theUDF(col("id")) spark.range(0, 1, 1, 1).withColumn("u", myUDFInstance) } def run(): Unit = { df.collect().foreach(println) } }
若要解决此错误,可以将
MyObjectInPackageCell
包装到可序列化的类中。某些使用
DataStreamWriter.foreachBatch
的情况将需要源代码更新。 此更改的原因是 Scala 2.12 会自动将 lambda 表达式转换为 SAM 类型,而这可能会导致多义性。例如,以下 Scala 代码无法编译:
streams .writeStream .foreachBatch { (df, id) => myFunc(df, id) }
若要修复此编译错误,请将
foreachBatch { (df, id) => myFunc(df, id) }
更改为foreachBatch(myFunc _)
或显式使用 Java API:foreachBatch(new VoidFunction2 ...)
。
由于用于处理 Hive 用户定义函数和 Hive SerDes 的 Apache Hive 版本已升级到 2.3,因此需要两项更改:
- Hive 的
SerDe
接口由AbstractSerDe
抽象类取代。 对于任何自定义 HiveSerDe
实现,需要迁移到AbstractSerDe
。 - 将
spark.sql.hive.metastore.jars
设置为builtin
意味着将使用 Hive 2.3 元存储客户端来访问 Databricks Runtime 7.x 的元存储。 如果需要访问基于 Hive 1.2 的外部元存储,请将spark.sql.hive.metastore.jars
设置为包含 Hive 1.2 jar 的文件夹。
- Hive 的
弃用的功能和删除的功能
- “跳过数据”索引已在 Databricks Runtime 4.3 中弃用,并已在 Databricks Runtime 7.x 中删除。 建议改用 Delta 表,它提供了经过改进的数据跳过功能。
- 在 Databricks Runtime 7.x 中,Apache Spark 的基础版本使用 Scala 2.12。 针对 Scala 2.11 编译的库可能会以意外的方式禁用 Databricks Runtime 7.x 群集,因此运行 Databricks Runtime 7.x 的群集不会安装配置为在所有群集上安装的库。 群集“库”选项卡显示状态“
Skipped
”和一条说明库处理方式更改的“弃用”消息。 但是,如果你的群集是在早期版本的 Databricks Runtime(在 Azure Databricks 平台 3.20 版发布到工作区之前的版本)上创建的,并且你现在将该群集编辑为使用 Databricks Runtime 7.x,则已配置为在所有群集上安装的任何库都将安装在该群集上。 在这种情况下,已安装的库中的所有不兼容的 JAR 都可能导致群集被禁用。 解决方法是克隆群集或创建新群集。
已知问题
- 如果 year 字段缺失,则使用模式字母“D”分析年份中的天会返回错误的结果。 这种情况可能发生在
to_timestamp
等 SQL 函数中,它使用模式字符串将日期/时间字符串分析为日期/时间值。 (SPARK-31939) - 如果键的值为 -0.0 和 0.0,则在子查询中进行联接/窗口/聚合操作可能会导致错误的结果。 (SPARK-31958)
- 窗口查询可能会由于意外的歧义自联接错误而失败。 (SPARK-31956)
- 使用
dropDuplicates
运算符的流式处理查询可能无法使用通过 Spark 2.x 编写的检查点重启。 (SPARK-31990)