迁移指南:SQL、数据集和数据框

从 Spark SQL 3.5.1 升级到 3.5.2

从 Spark SQL 3.5.0 升级到 3.5.1

从 Spark SQL 3.4 升级到 3.5

从 Spark SQL 3.3 升级到 3.4

从 Spark SQL 3.2 升级到 3.3

从 Spark SQL 3.1 升级到 3.2

从 Spark SQL 3.0 升级到 3.1

从 Spark SQL 3.0.1 升级到 3.0.2

从 Spark SQL 3.0 升级到 3.0.1

从 Spark SQL 2.4 升级到 3.0

数据集/数据框 API

DDL 语句

用户定义函数和内置函数

查询引擎

数据源

其他

从 Spark SQL 2.4.7 升级到 2.4.8

从 Spark SQL 2.4.5 升级到 2.4.6

从 Spark SQL 2.4.4 升级到 2.4.5

从 Spark SQL 2.4.3 升级到 2.4.4

从 Spark SQL 2.4 升级到 2.4.1

从 Spark SQL 2.3 升级到 2.4

从 Spark SQL 2.2 升级到 2.3

空类型 空类型 整数类型 长整型 十进制类型(38,0) 双精度类型 日期类型 时间戳类型 字符串类型 整数类型 整数类型 整数类型 长整型 十进制类型(38,0) 双精度类型 字符串类型 字符串类型 字符串类型 长整型 长整型 长整型 长整型 十进制类型(38,0) 字符串类型 字符串类型 字符串类型 字符串类型 十进制类型(38,0)* 十进制类型(38,0) 十进制类型(38,0) 十进制类型(38,0) 十进制类型(38,0) 字符串类型 字符串类型 字符串类型 字符串类型 双精度类型 双精度类型 双精度类型 字符串类型 字符串类型 双精度类型 字符串类型 字符串类型 字符串类型 日期类型 日期类型 字符串类型 字符串类型 字符串类型 字符串类型 日期类型 时间戳类型 字符串类型 时间戳类型 时间戳类型 字符串类型 字符串类型 字符串类型 字符串类型 时间戳类型 时间戳类型 字符串类型 字符串类型 字符串类型 字符串类型 字符串类型 字符串类型 字符串类型 字符串类型 字符串类型 字符串类型

请注意,对于 DecimalType(38,0),上面的表格故意没有涵盖所有其他比例和精度的组合,因为目前我们只推断像 `BigInteger`/`BigInt` 这样的十进制类型。例如,1.1 被推断为双精度类型。

从 Spark SQL 2.1 升级到 2.2

从 Spark SQL 2.0 升级到 2.1

从 Spark SQL 1.6 升级到 2.0

从 Spark SQL 1.5 升级到 1.6

   ./sbin/start-thriftserver.sh \
--conf spark.sql.hive.thriftServer.singleSession=true \
     ...
   

从 Spark SQL 1.4 升级到 1.5

从 Spark SQL 1.3 升级到 1.4

数据框数据读写接口

根据用户反馈,我们创建了一个新的、更流畅的API用于读取数据 ( SQLContext.read ) 和写入数据 ( DataFrame.write ), 并弃用了旧的API (例如, SQLContext.parquetFile , SQLContext.jsonFile ).

请参阅 SQLContext.read 的API文档 ( Scala , Java , Python ) 和 DataFrame.write 的更多信息 ( Scala , Java , Python )。

DataFrame.groupBy 保留分组列

根据用户反馈,我们更改了 DataFrame.groupBy().agg() 的默认行为,以保留结果中的分组列 DataFrame 。要保持1.3中的行为,请将 spark.sql.retainGroupColumns 设置为 false

import pyspark.sql.functions as func
# 在 1.3.x 中,为了让分组列 "department" 显示, 
# 它必须作为 agg 函数调用的一部分明确包含。
df.groupBy("department").agg(df["department"], func.max("age"), func.sum("expense"))
# 在 1.4+ 中,分组列 "department" 会自动包含。
df.groupBy("department").agg(func.max("age"), func.sum("expense"))
# 通过以下方式恢复到 1.3.x 行为(不保留分组列):
sqlContext.setConf("spark.sql.retainGroupColumns", "false")
// 在1.3.x中,为了使分组列“department”显示出来,
// 它必须作为agg函数调用的一部分显式包含。
df.groupBy("department").agg($"department", max("age"), sum("expense"))
// 在1.4+中,分组列“department”会自动包含。
df.groupBy("department").agg(max("age"), sum("expense"))
// 通过下面的方式恢复到1.3行为(不保留分组列):
sqlContext.setConf("spark.sql.retainGroupColumns", "false")
// 在 1.3.x 中,为了使分组列“department”能够显示,
// 必须将其显式包含在 agg 函数调用中。
df.groupBy("department").agg(col("department"), max("age"), sum("expense"));
// 在 1.4+ 中,分组列“department”会自动包含。
df.groupBy("department").agg(max("age"), sum("expense"));
// 通过以下方式恢复到 1.3 行为(不保留分组列):
sqlContext.setConf("spark.sql.retainGroupColumns", "false");

在DataFrame.withColumn上的行为变化

在1.4之前,DataFrame.withColumn()仅支持添加一列。即使结果DataFrame中可能存在同名的列,该列也将始终作为具有指定名称的新列添加。自1.4以来,DataFrame.withColumn()支持添加与所有现有列名称不同的列,或替换同名的现有列。

请注意,这一更改仅适用于Scala API,而不适用于PySpark和SparkR。

从 Spark SQL 1.0-1.2 升级到 1.3

在Spark 1.3中,我们从Spark SQL中移除了“Alpha”标签,并作为此的一部分对可用的API进行了清理。从Spark 1.3开始,Spark SQL将与1.X系列中的其他版本提供二进制兼容性。此兼容性保证不包括被明确标记为不稳定的API(即DeveloperAPI或Experimental)。

SchemaRDD重命名为DataFrame

用户在升级到 Spark SQL 1.3 时最明显的变化是 SchemaRDD 被重命名为 DataFrame 。这主要是因为 DataFrame 不再直接从 RDD 继承,而是通过自己的实现提供大部分 RDD 提供的功能。DataFrame 仍然可以通过调用 .rdd 方法转换为 RDD。

在Scala中,有一个类型别名从 SchemaRDD DataFrame 用以提供某些用例的源兼容性。仍然建议用户更新他们的代码以使用 DataFrame 。Java和Python用户需要更新他们的代码。

Java和Scala API的统一

在Spark 1.3之前,有单独的Java兼容类( JavaSQLContext JavaSchemaRDD ),它们镜像了Scala API。在Spark 1.3中,Java API和Scala API已统一。无论使用哪种语言的用户都应使用 SQLContext DataFrame 。一般来说,这些类试图使用两种语言都能使用的类型(即使用 Array 而不是特定于语言的集合)。在某些情况下,如果没有通用类型(例如,用于传递闭包或Maps)则使用函数重载。

此外,Java特定类型API已经被移除。Scala和Java的用户应该使用 org.apache.spark.sql.types 中的类来以编程方式描述架构。

隐式转换的隔离与dsl包的移除(仅限Scala)

在Spark 1.3之前的许多代码示例中,通常以 import sqlContext._ 开头,这将所有函数导入到作用域中。在Spark 1.3中,我们将将 RDD 转换为 DataFrame 的隐式转换隔离到了 SQLContext 内的一个对象中。用户现在应该编写 import sqlContext.implicits._

此外,隐式转换现在仅增加由 Product (即,案例类或元组)组成的 RDD 的 toDF 方法,而不是自动应用。

在DSL中使用函数时(现在已被 DataFrame API 替代),用户通常会导入 org.apache.spark.sql.catalyst.dsl 。而应该使用公共数据框函数API: import org.apache.spark.sql.functions._

在org.apache.spark.sql中移除类型别名(仅限Scala)

Spark 1.3 移除了基础 sql 包中与 DataType 相关的类型别名。用户应改为导入 org.apache.spark.sql.types 中的类。

UDF 注册已转移至 sqlContext.udf (Java & Scala)

用于注册 UDF 的函数,无论是在 DataFrame DSL 还是 SQL 中,都已移入 SQLContext 中的 udf 对象。

sqlContext.udf.register("strLen", (s: String) => s.length())
sqlContext.udf().register("strLen", (String s) -> s.length(), DataTypes.IntegerType);

Python UDF 注册保持不变。

与 Apache Hive 的兼容性

Spark SQL旨在与Hive Metastore、SerDes和UDF兼容。 目前,Hive SerDes和UDF是基于内置的Hive, Spark SQL可以连接到不同版本的Hive Metastore(从0.12.0到2.3.9和3.0.0到3.1.3。另请参见 与不同版本的Hive Metastore交互 )。

在现有Hive仓库中部署

Spark SQL Thrift JDBC 服务器旨在与现有 Hive 安装“开箱即用”兼容。您无需修改现有 Hive Metastore,也不需要改变表的数据位置或分区。

支持的Hive特性

Spark SQL 支持绝大多数 Hive 功能,例如:

不支持的Hive功能

下面是我们尚未支持的Hive特性列表。大多数这些特性在Hive部署中很少使用。

深奥的Hive特性

Hive 输入/输出格式

Hive 优化

一些Hive优化尚未包含在Spark中。其中一些(例如索引)由于Spark SQL的内存计算模型而重要性较低。其他一些则计划在未来的Spark SQL版本中发布。

Hive 用户自定义函数/用户自定义表函数/用户自定义聚合函数

并不是所有的 Hive UDF/UDTF/UDAF 的 API 都被 Spark SQL 支持。以下是未支持的 API:

不兼容的 Hive UDF

以下是Hive和Spark生成不同结果的场景: