SQL Server 大数据群集 Spark 3 升级指南

适用范围:SQL Server 2019 (15.x)

重要

Microsoft SQL Server 2019 大数据群集附加产品将停用。 对 SQL Server 2019 大数据群集的支持将于 2025 年 2 月 28 日结束。 具有软件保障的 SQL Server 2019 的所有现有用户都将在平台上获得完全支持,在此之前,该软件将继续通过 SQL Server 累积更新进行维护。 有关详细信息,请参阅公告博客文章Microsoft SQL Server 平台上的大数据选项

本文包含有关将 Apache Spark 2.4 工作负载迁移到 Spark 版本 3.1 的重要信息和指南。 若要从 SQL Server 大数据群集 CU12 升级到 CU13 及更高版本,必须阅读本文。

SQL Server 大数据群集 上的 Apache Spark 3 简介

在累积更新 12 (CU12) 之前,大数据群集依赖于 Apache Spark 2.4 系列,该系列已于 2021 年 5 月停用。 与我们对持续改进 Apache Spark 引擎引入的大数据和机器学习功能的承诺一致,CU13 引入了当前版本的 Apache Spark(版本 3.1.2)。

新的性能基线

与大数据处理工作负载相比,这一新版本的 Apache Spark 带来了性能优势。 在我们的测试中使用参考 TCP-DS 10TB 工作负载,能够将运行时从 4.19 小时减少到 2.96 小时,仅通过在 SQL Server 大数据群集 上使用相同的硬件和配置文件切换引擎,无需其他应用程序优化,就提升了 29.36% 。 单个查询运行时平均提升 36%。

通过单击仪表板打开提交菜单

升级指南

Spark 3 是一个主要版本,包含中断性变更。 遵循 SQL Server 系列中相同的既定最佳做法,建议:

  1. 完整阅读本文。
  2. 查看官方 Apache Spark 3 迁移指南
  3. 在当前环境中并行部署新的大数据群集版本 CU13。
  4. (可选)利用新的 azdata HDFS 分布式复制功能,获得验证所需的一部分数据。
  5. 在升级之前,使用 Spark 3 验证当前工作负载。
  6. 重新评估代码和表定义策略中强制实施的 Spark 优化。 Spark 3 新增了随机、分区和自适应查询执行增强功能。 这是一个很好的机会,可以用来重新评估以前的决策并尝试利用较新引擎的现成功能。

群集升级期间会发生什么情况?

群集升级过程将使用新版本和刷新的适用于 Apache Spark 的运行时部署 Spark Pod。 升级后,将不会再存在 Spark 2.4 组件。

通过配置框架进行的持续配置更改将会保留。

直接加载到 HDFS 中的用户库和项目将会保留。 但是,请确保这些库和项目与 Spark 3 兼容。

警告

直接对 Pod 进行的自定义将会丢失,请确保验证并重新应用这些自定义项(如果仍适用于 Spark 3)。

中断性变更

Spark 3 与 2.4 并非完全向后兼容,中断性变更主要包含三部分:

  • Spark 3 使用的 Scala 2.12 与 Spark 2.4 使用的 Scala 2.11 不兼容
  • Spark 3 API 更改和弃用
  • 适用于 Apache Spark 库的 SQL Server 大数据群集运行时更新

Spark 3 使用的 Scala 2.12 与 Scala 2.11 不兼容

如果运行基于 Scala 2.11 jar 的 Spark 作业,需使用 Scala 2.12 重新生成它。 Scala 2.11 和 2.12 大多是源代码兼容,但不是二进制兼容。 有关详细信息,请参阅 Scala 2.12.0

需要进行以下更改:

  1. 更改所有 Scala 依赖项的 Scala 版本。
  2. 更改所有 Spark 依赖项的 Spark 版本。
  3. 更改除外部依赖项 (spark-sql-kafka-0-10) 之外的所有 Spark 依赖项已提供的范围。

下面是示例 pom.xml:

  <properties>
    <spark.version>3.1.2</spark.version>
    <scala.version.major>2.12</scala.version.major>
    <scala.version.minor>10</scala.version.minor>
    <scala.version>${scala.version.major}.${scala.version.minor}</scala.version>
  </properties>
 
  <dependencies>
 
    <dependency>
      <groupId>org.scala-lang</groupId>
      <artifactId>scala-library</artifactId>
      <version>${scala.version}</version>
      <scope>provided</scope>
    </dependency>
 
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-core_${scala.version.major}</artifactId>
      <version>${spark.version}</version>
     <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-sql_${scala.version.major}</artifactId>
      <version>${spark.version}</version>
      <scope>provided</scope>
    </dependency>
 
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-sql-kafka-0-10_${scala.version.major}</artifactId>
      <version>${spark.version}</version>
    </dependency>
    
  </dependencies>

Spark 3 API 更改和弃用

查看官方 Apache Spark 3 迁移指南,其中详细介绍了所有 API 更改。

一些捕获的要点包括:

重大更改 操作
Spark 3 中删除了 spark-submit 参数 yarn-clientyarn-clustermodes 请改用 spark-submit --master yarn --deploy-mode client--deploy-mode cluster
详细信息请参阅 https://spark.apache.org/docs/latest/running-on-yarn.html
HiveContext 类已删除 请改用 SparkSession.builder.enableHiveSupport()
在 TRIM 方法中,参数的顺序是相反的 使用 TRIM(str, trimStr) 而不是 TRIM(trimStr, str)
由于升级到 Scala 2.12,DataStreamWriter.foreachBatch 不是与 Scala 程序兼容的源代码 更新 Scala 源代码,以区分 Scala 函数和 Java Lambda。

适用于 Apache Spark 库的 SQL Server 大数据群集运行时更新

适用于 Apache Spark 的 SQL Server 大数据群集运行时规范中介绍的,所有默认 Python、R 和 Scala 库在 CU13 版本上均已更新。 此外,还添加了许多库,以提供更好的开箱即用体验。

  1. 确保工作负载适用于较新的库集。
  2. 查看自定义加载库现在是否属于默认包基线,并调整作业规范来删除自定义库,以允许作业使用附带的库。

常见问题

如何解决奇怪的 java.lang.NoSuchMethodError 错误或 java.lang.ClassNotFoundException 异常

此错误很可能是由 Spark 或 Scala 版本冲突引起的。 仔细检查以下内容并重新生成项目。

  1. 确保所有 Scala 版本已更新。
  2. 请确保使用正确的 Scala 版本和 Spark 版本更新所有 Spark 依赖项。
  3. 确保所有 Spark 依赖项都提供了 spark-sql-kafka-0-10 以外的范围。

因日历模式更改而引发 SparkUpgradeException

Spark 3.0 日历模型中有一些更改。 在 Spark SQL 中编写日历列时,可能会看到如下所示的异常:

Caused by: org.apache.spark.SparkUpgradeException: 
You may get a different result due to the upgrading of Spark 3.0:
writing dates before 1582-10-15 or timestamps before 1900-01-01T00:00:00Z into Parquet INT96 files can be dangerous,
as the files may be read by Spark 2.x or legacy versions of Hive later, 
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.int96RebaseModeInWrite to 'LEGACY' to 
rebase the datetime values w.r.t. the calendar difference during writing, to get maximum interoperability. 
Or set spark.sql.legacy.parquet.int96RebaseModeInWrite to 'CORRECTED' to 
write the datetime values as it is, if you are 100% sure that the written files 
will only be read by Spark 3.0+ or other systems that use Proleptic Gregorian calendar.

解决方案:按如上所述将配置 spark.sql.legacy.parquet.int96RebaseModeInWrite 设置为 LEGACY 或 CORRECTED。 下面是 PySpark 代码中可能的解决方案:

spark.conf.set("spark.sql.legacy.parquet.int96RebaseModeInWrite","CORRECTED")

后续步骤

有关详细信息,请参阅 SQL Server 大数据群集 简介