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 转换为 intdouble 转换为 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) 返回 1cast(' 1\t' as boolean) 返回 truecast('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.createExternalTableSparkSession.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。 对于 FloatTypeDoubleType,它在空字符串上将失败并引发异常。 自 Spark 3.0 起,将禁止使用空字符串,并对除 StringTypeBinaryType 以外的数据类型引发异常。
  • 自 Spark 3.0 起,from_json 函数支持两种模式:PERMISSIVEFAILFAST。 可以通过 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 转换为 intdouble 转换为 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 及更低版本中,可以通过 CreateMapStringToMap 等内置函数来创建具有重复键的映射。具有重复键的映射的行为是不确定的,例如,映射查找会遵循首先出现的重复键,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。 对于 FloatTypeDoubleTypeDateTypeTimestampType,它在空字符串上将失败并引发异常。 Spark 3.0 禁止使用空字符串,并且将对除 StringTypeBinaryType 以外的数据类型引发异常。 可以通过将 spark.sql.legacy.json.allowEmptyString.enabled 设置为 true 来还原以前允许空字符串的行为。
  • 在 Spark 3.0 中,如果文件或子目录在递归目录列表期间消失(即它们出现在中间列表中,但由于并发文件删除或对象存储一致性问题而在递归目录列表的后续阶段无法读取或列出),那么除非 spark.sql.files.ignoreMissingFilestrue(默认为 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.timeZoneTIMESTAMP 文本转换为字符串。 在 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_timestampdate_formatto_unix_timestampfrom_unixtimeto_dateto_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 来还原旧的行为。
    • weekofyearweekdaydayofweekdate_truncfrom_utc_timestampto_utc_timestampunix_timestamp 函数使用 java.time API 来计算每年的第几周、每周的第几天以及转换自/到 UTC 时区的 TimestampType 值。
    • JDBC 选项 lowerBoundupperBound 的转换方式与将字符串强制转换为 TimestampType/DateType 值的方式相同。 该转换基于前公历以及 SQL 配置 spark.sql.session.timeZone 定义的时区。 在 Spark 2.4 及更低版本中,该转换基于混合日历(儒略历 + 公历)和默认系统时区。
    • TIMESTAMPDATE 文本进行格式设置。
    • 从字符串创建类型为 TIMESTAMPDATE 的文本。 在 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 系统时区。 默认时区的不同源可能会更改类型为 TIMESTAMPDATE 的文本的行为。

Apache Hive

  • 在 Spark 3.0 中,我们将内置的 Hive 版本从 1.2 升级到 2.3,这会带来以下影响:
    • 可能需要根据要连接的 Hive 元存储的版本设置 spark.sql.hive.metastore.versionspark.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 原生表读取器和文件读取器。

MLlib

  • OneHotEncoder(在 2.3 中已弃用)在 3.0 中已删除,OneHotEncoderEstimator 现重命名为 OneHotEncoder
  • org.apache.spark.ml.image.ImageSchema.readImages(在 2.3 中已弃用)在 3.0 中已删除。 请改用 spark.read.format('image')
  • 具有参数 Int runsorg.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.LogisticRegressionspark.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.LinearRegressionelasticNetParam = 0.0 配合使用。 请注意,RidgeRegressionWithSGD 的默认 regParam 为 0.01,而 LinearRegression 的默认值为0.0。
  • org.apache.spark.mllib.regression.LassoWithSGD(在 2.0 中已弃用)在 3.0 中已删除。 将 org.apache.spark.ml.regression.LinearRegressionelasticNetParam = 1.0 配合使用。 请注意,LassoWithSGD 的默认 regParam 为 0.01,而 LinearRegression 的默认值为0.0。
  • org.apache.spark.mllib.regression.LinearRegressionWithSGD(在 2.0 中已弃用)在 3.0 中已删除。 请改用 org.apache.spark.ml.regression.LinearRegressionLBFGS
  • org.apache.spark.mllib.clustering.KMeans.getRunssetRuns(在 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 抽象类取代。 对于任何自定义 Hive SerDe 实现,需要迁移到 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 的文件夹。

弃用的功能和删除的功能

  • “跳过数据”索引已在 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)