从Spark SQL 2.4升级到3.0哪些变化
Dataset/DataFrame API
-
在Spark 3.0中,Dataset和DataFrame API的
unionAll不再被弃用,它是union的别名。 -
在Spark 2.4及以下版本中,如果键的类型为非结构化类型(例如int、string、array等),则
Dataset.groupByKey的结果会导致带有错误名称"value"的分组数据集。这种行为令人困惑,并使聚合查询的模式出乎意料。例如,ds.groupByKey(...).count()的模式是(value, count)。从Spark 3.0开始,我们将分组属性命名为"key"。通过新添加的配置spark.sql.legacy.dataset.nameNonStructGroupingKeyAsValue,可以保留旧的行为,默认值为false。 -
在Spark 3.0中,列元数据将始终在API
Column.name和Column.as中传播。在Spark 2.4及更早版本中,NamedExpression的元数据在调用API时作为新列的explicitMetadata设置,即使底层的NamedExpression更改了元数据,也不会更改。要恢复Spark 2.4之前的行为,可以使用带有显式元数据的APIas(alias: String, metadata: Metadata)。
DDL语句
-
在Spark 3.0中,当向表列插入不同数据类型的值时,将根据ANSI SQL标准执行类型转换。某些不合理的类型转换,如将
string转换为int或double转换为boolean是不允许的。如果值超出列的数据类型范围,则会抛出运行时异常。在Spark 2.4及以下版本中,只要是有效的Cast,在插入表时允许进行类型转换。当向整数字段插入超出范围的值时,插入的是值的低位(与Java/Scala数值类型转换相同)。例如,如果将257插入到字节类型的字段中,结果为1。此行为由选项spark.sql.storeAssignmentPolicy控制,默认值为"ANSI"。将该选项设置为"Legacy"可以恢复之前的行为。 -
ADD JAR命令以前返回的是一个带有单个值0的结果集,现在返回一个空的结果集。 -
Spark 2.4及以下版本:即使指定的键是
SparkConf条目的键,并且没有生效,SET命令也可以正常工作,而不会发出任何警告,因为该命令不会更新SparkConf,但这种行为可能会让用户感到困惑。在3.0中,如果使用了SparkConf键,该命令将失败。可以通过将spark.sql.legacy.setCommandRejectsSparkCoreConfs设置为false来禁用此检查。 -
刷新缓存表将触发取消缓存操作,然后进行缓存(懒加载)操作。在Spark 2.4及以下版本中,在取消缓存操作之前并没有保留缓存名称和存储级别。因此,缓存名称和存储级别可能会意外更改。在Spark 3.0中,首先保留缓存名称和存储级别以进行缓存重建。这有助于在刷新表时保持一致的缓存行为。
-
在Spark 3.0中,以下属性列出的命令被保留;如果在
CREATE DATABASE ... WITH DBPROPERTIES和ALTER TABLE ... SET TBLPROPERTIES等位置指定了保留的属性,命令将失败。您需要使用它们特定的子句来指定它们,例如CREATE DATABASE test COMMENT 'any comment' LOCATION 'some path'。您可以将spark.sql.legacy.notReserveProperties设置为true,以忽略ParseException,在这种情况下,这些属性将被静默删除,例如:SET DBPROPERTIES('location'='/tmp')将不起作用。在Spark 2.4及以下版本中,这些属性既不是保留属性,也没有副作用,例如:SET DBPROPERTIES('location'='/tmp')不会更改数据库的位置,而只会创建一个无头属性,就像'a'='b'一样。属性(区分大小写) 数据库保留 表保留 备注 provider 否 是 对于表,使用 USING子句来指定。一旦设置,将无法更改。location 是 是 对于数据库和表,使用 LOCATION子句来指定。owner 是 是 对于数据库和表,由运行Spark并创建表的用户确定。 -
在Spark 3.0中,您可以使用
ADD FILE命令添加文件目录。以前只能使用此命令添加单个文件。要恢复到以前版本的行为,请将spark.sql.legacy.addSingleFileInAddFile设置为true。 -
在Spark 3.0中,如果表不存在,
SHOW TBLPROPERTIES会抛出AnalysisException异常。在Spark 2.4及以下版本中,此情况会导致NoSuchTableException异常。 -
在Spark 3.0中,
SHOW CREATE TABLE始终返回Spark DDL,即使给定的表是Hive SerDe表。要生成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中,
date_add和date_sub函数只接受int、smallint、tinyint作为第二个参数;不再允许使用分数和非文字字符串。例如:date_add(cast('1964-05-23' as date), '12.34')会导致AnalysisException异常。需要注意的是,字符串字面量仍然被允许使用,但如果字符串内容不是有效的整数,Spark会抛出AnalysisException异常。在Spark 2.4及以下版本中,如果第二个参数是分数或字符串值,它会被强制转换为整数值,并且结果将是一个日期值,即1964-06-04。 -
在Spark 3.0中,
percentile_approx函数及其别名approx_percentile只接受范围在[1, 2147483647]之间的整数值作为其第三个参数accuracy,不再允许使用分数和字符串类型。例如,percentile_approx(10.0, 0.2, 1.8D)会导致AnalysisException异常。在Spark 2.4及以下版本中,如果accuracy是分数或字符串值,它会被强制转换为整数值,percentile_approx(10.0, 0.2, 1.8D)会被视为percentile_approx(10.0, 0.2, 1),返回结果为10.0。 -
在Spark 3.0中,如果对
MapType的元素应用哈希表达式,则会抛出分析异常。要恢复到Spark 3.0之前的行为,可以将spark.sql.legacy.allowHashOnMapType设置为true。 -
在Spark 3.0中,当无参数调用
array/map函数时,它将返回一个元素类型为NullType的空集合。在Spark 2.4及以下版本中,它返回一个元素类型为StringType的空集合。要恢复到Spark 3.0之前的行为,可以将spark.sql.legacy.createEmptyCollectionUsingStringType设置为true。 -
在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)。 -
在Spark 3.0中,不能再使用内置函数(如
CreateMap、MapFromArrays等)创建具有映射类型键的映射值。用户可以使用map_entries函数将映射转换为array<struct<key, value>>来解决此问题。此外,用户仍然可以从数据源或Java/Scala集合中读取具有映射类型键的映射值,尽管不鼓励这样做。 -
在Spark 3.0中,不能再使用内置函数(如
CreateMap、StringToMap等)创建具有重复键的映射。如果找到重复键,Spark会抛出RuntimeException异常。可以将spark.sql.mapKeyDedupPolicy设置为LAST_WIN以使用最后一个键策略进行键去重。用户仍然可以从不强制执行键去重的数据源(例如Parquet)中读取具有重复键的映射值,但行为是未定义的。 -
在Spark 3.0中,默认情况下不允许使用
org.apache.spark.sql.functions.udf(AnyRef, DataType)方法创建未指定返回类型的UDF。建议删除返回类型参数以自动切换到类型化的Scala UDF,或将spark.sql.legacy.allowUntypedScalaUDF设置为true以继续使用它。在Spark 2.4及以下版本中,如果org.apache.spark.sql.functions.udf(AnyRef, DataType)接收到一个带有原始类型参数的Scala闭包,则返回的UDF在输入值为null时返回null。然而,在Spark 3.0中,如果输入值为null,UDF将返回Java类型的默认值。例如,val f = udf((x: Int) => x, IntegerType),如果列x为null,在Spark 2.4及以下版本中,f($"x")返回null;而在Spark 3.0中返回0。这个行为变化是因为Spark 3.0默认使用Scala 2.12构建。 -
在Spark 3.0中,高阶函数
exists遵循三值布尔逻辑。即,如果predicate返回任何null,并且没有获得true,则exists返回null而不是false。例如,exists(array(1, null, 3), x -> x % 2 == 0)返回null。可以通过将spark.sql.legacy.followThreeValuedLogicInArrayExists设置为false来恢复先前的行为。 -
在Spark 3.0中,
add_months函数不会将结果日期调整为月底,即使原始日期是月底也是如此。例如,select add_months(DATE'2019-02-28', 1)的结果是2019-03-28。在Spark 2.4及以下版本中,如果原始日期是月底,添加一个月会将结果日期调整为当月的最后一天。例如,将一个月加到2019-02-28上的结果是2019-03-31。 -
在Spark 2.4及以下版本中,
current_timestamp函数仅返回毫秒精度的时间戳。在Spark 3.0中,如果系统上的底层时钟支持微秒精度,则函数可以返回微秒精度的结果。 -
在Spark 3.0中,执行器端会像其他UDF一样执行没有参数的Java UDF。在Spark 2.4及以下版本中,只有没有参数的Java UDF在Driver端执行,并将结果传播到执行器端,这在某些情况下可能更高效,但也会导致一些正确性问题。
-
java.lang.Math的log、log1p、exp、expm1和pow的结果可能因平台而异。在Spark 3.0中,与java.lang.StrictMath一致,等价的SQL函数(包括LOG10等相关SQL函数)的结果与java.lang.Math一致。在几乎所有情况下,它们的返回值没有任何差异,差异非常小,但在x86平台上可能与java.lang.Math不完全匹配,例如,log(3.0)的值在Math.log()和StrictMath.log()之间变化。 -
在Spark 3.0中,当将字符串字面量转换为
Double或Float类型时,Cast函数对诸如’Infinity’、‘+Infinity’、‘-Infinity’、‘NaN’、‘Inf’、‘+Inf’、'-Inf’这样的字符串字面量进行不区分大小写处理,以确保与其他数据库系统的兼容性。下表显示了此行为变化的示例:操作 Spark 3.0之前的结果 Spark 3.0的结果 CAST(‘infinity’ AS DOUBLE) NULL Double.PositiveInfinity CAST(‘+infinity’ AS DOUBLE) NULL Double.PositiveInfinity CAST(‘inf’ AS DOUBLE) NULL Double.PositiveInfinity CAST(‘inf’ AS DOUBLE) NULL Double.PositiveInfinity CAST(‘-infinity’ AS DOUBLE) NULL Double.NegativeInfinity CAST(‘-inf’ AS DOUBLE) NULL Double.NegativeInfinity CAST(‘infinity’ AS FLOAT) NULL Float.PositiveInfinity CAST(‘+infinity’ AS FLOAT) NULL Float.PositiveInfinity CAST(‘inf’ AS FLOAT) NULL Float.PositiveInfinity CAST(‘+inf’ AS FLOAT) NULL Float.PositiveInfinity CAST(‘-infinity’ AS FLOAT) NULL Float.NegativeInfinity CAST(‘-inf’ AS FLOAT) NULL Float.NegativeInfinity CAST(‘nan’ AS DOUBLE) NULL Double.Nan CAST(‘nan’ AS FLOAT) NULL Float.NaN -
在Spark 3.0中,将间隔值转换为字符串类型时,不再包含"interval"前缀,例如
1 days 2 hours。在Spark 2.4及以下版本中,字符串包含"interval"前缀,如interval 1 days 2 hours。 -
在Spark 3.0中,将字符串值转换为整数类型(tinyint、smallint、int和bigint)、日期时间类型(date、timestamp和interval)和布尔类型时,在转换之前会去除前导和尾随的空白字符(ASCII 32以下)。例如,
cast(' 1\t' as int)的结果是1,cast(' 1\t' as boolean)的结果是true,cast('2019-10-10\tas date)的结果是日期值2019-10-10`。在Spark 2.4及以下版本中,将字符串转换为整数和布尔值时,不会去除两端的空白字符;对于日期时间类型,只会去除尾随的空格(ASCII 32)。
Spark版本3.0中的查询引擎变化
-
在Spark 3.0及以下版本中,不再支持类似
FROM <table>或FROM <table> UNION ALL FROM <table>这样的SQL查询。在Hive风格的FROM <table> SELECT <expr>中,SELECT子句是不可忽略的。Hive和Presto都不支持这种语法。这些查询在Spark 3.0中被视为无效。 -
在Spark 3.0中,间隔字面量语法不再允许多个from-to单位。例如,
SELECT INTERVAL '1-1' YEAR TO MONTH '2-2' YEAR TO MONTH'会抛出解析异常。 -
在Spark 3.0中,科学计数法表示的数字(例如
1E2)将被解析为Double类型。而在Spark 3.0之前的版本中,它们被解析为Decimal类型。要恢复到Spark 3.0之前的行为,可以将spark.sql.legacy.exponentLiteralAsDecimal.enabled设置为true。 -
在Spark 3.0中,日时区间字符串将根据
from和to边界转换为区间值。如果输入字符串与指定边界定义的模式不匹配,则会抛出ParseException异常。例如,interval '2 10:20' hour to minute会抛出异常,因为期望的格式是[+|-]h[h]:[m]m。而在Spark 3.0之前的版本中,不考虑from边界,只使用to边界来截断结果的区间。例如,上述示例中的日时区间字符串会转换为interval 10 hours 20 minutes。要恢复到Spark 3.0之前的行为,可以将spark.sql.legacy.fromDayTimeString.enabled设置为true。 -
在Spark 3.0中,默认情况下不允许负数精度的Decimal类型。例如,类似
1E10BD的字面量的数据类型为DecimalType(11, 0)。而在Spark 3.0之前的版本中,数据类型为DecimalType(2, -9)。要恢复到Spark 3.0之前的行为,可以将spark.sql.legacy.allowNegativeScaleOfDecimal设置为true。 -
在Spark 3.0中,一元算术运算符加号(
+)只接受字符串、数值和时间区间类型的值作为输入。此外,带有整数字符串表示的+会被强制转换为Double值,例如+'1'返回1.0。而在Spark 3.0之前的版本中,该运算符会被忽略,对于它没有类型检查,因此带有+前缀的所有类型值都是有效的,例如+ array(1, 2)是有效的,并且结果为[1, 2]。此外,对于它根本没有类型强制转换,例如,在Spark 2.4中,+'1'的结果是字符串1。 -
在Spark 3.0中,如果数据集查询包含由自身连接引起的列引用歧义,查询将失败。一个典型的例子是:
val df1 = ...; val df2 = df1.filter(...);,然后df1.join(df2, df1("a") > df2("a"))返回一个空结果,这很令人困惑。这是因为Spark无法解析指向自身连接的数据集列引用,并且df1("a")恰好与Spark中的df2("a")相同。要恢复到Spark 3.0之前的行为,可以将spark.sql.analyzer.failAmbiguousSelfJoin设置为false。 -
在Spark 3.0中,引入了
spark.sql.legacy.ctePrecedencePolicy配置项,用于控制嵌套WITH子句中名称冲突的行为。默认值为EXCEPTION,Spark会抛出AnalysisException异常,强制用户选择他们想要的特定替换顺序。如果设置为CORRECTED(推荐),内部CTE定义优先于外部定义。例如,将该配置设置为CORRECTED,WITH t AS (SELECT 1), t2 AS (WITH t AS (SELECT 2) SELECT * FROM t) SELECT * FROM t2返回2,而将其设置为LEGACY时,结果为1,这是Spark 2.4及以下版本的行为。 -
在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 2.4及以下版本中,无效的时区ID在处理from_utc_timestamp等函数时会被默默地忽略并替换为GMT时区。在Spark 3.0中,将拒绝这些无效的时区ID,并抛出
java.time.DateTimeException异常。 -
在Spark 3.0中,解析、格式化和转换日期、时间戳以及提取年、日等子组件时使用Proleptic Gregorian日历。Spark 3.0使用基于ISO年表的
java.time包中的Java 8 API类进行这些操作。而在Spark 2.4及以下版本中,这些操作是使用混合日历(朱利安+格里高利)(Julian + Gregorian)进行的。这些变化影响了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进行时间戳/日期字符串转换,并且支持的模式在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值相同。该转换基于Proleptic Gregorian日历,并由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字面量的行为。
-
-
在Spark 3.0中,
TIMESTAMP字面量转换为字符串时使用SQL配置spark.sql.session.timeZone。而在Spark 2.4及以下版本中,转换使用Java虚拟机的默认时区。 -
在Spark 3.0中,Spark将
String在与日期/时间戳进行二进制比较时转换为Date/Timestamp。可以通过将spark.sql.legacy.typeCoercion.datetimeToString.enabled设置为true来恢复先前将Date/Timestamp转换为String的行为。 -
在Spark 3.0中,支持特殊值在从字符串到日期和时间戳的转换中。这些特殊值只是一种简写的标记,当读取时被转换为普通的日期或时间戳值。对于日期,支持以下字符串值:
epoch [zoneId]- 1970-01-01today [zoneId]- 当前日期(根据spark.sql.session.timeZone指定的时区)yesterday [zoneId]- 当前日期减1天tomorrow [zoneId]- 当前日期加1天now- 运行当前查询的日期。与today相同
例如,
SELECT date 'tomorrow' - date 'yesterday';应该输出2。以下是特殊的时间戳值:epoch [zoneId]- 1970-01-01 00:00:00+00(Unix系统时间零点)today [zoneId]- 今天的午夜yesterday [zoneId]- 昨天的午夜tomorrow [zoneId]- 明天的午夜now- 当前查询开始时间
例如,
SELECT timestamp 'tomorrow';。 -
自Spark 3.0起,使用
EXTRACT表达式从日期/时间戳值中提取秒字段时,结果将是一个带有两位秒部分和六位小数部分的DecimalType(8, 6)值,精确到微秒。例如,extract(second from to_timestamp('2019-09-20 10:10:10.1'))的结果是10.100000。而在Spark 2.4及更早版本中,它返回一个IntegerType值,对于前面的示例,结果为10。
数据源变化
-
在Spark 3.0及以下版本中,当使用Spark本机数据源(parquet/orc)读取Hive SerDe表时,Spark不再推断实际文件模式并更新元数据存储中的表模式。这对终端用户不应该造成任何问题,但如果确实存在问题,可以将
spark.sql.hive.caseSensitiveInferenceMode设置为INFER_AND_SAVE。 -
在Spark 3.0中,如果分区列的值无法转换为用户提供的模式,则将分区列的值视为null。在3.0中,将使用用户提供的模式对分区列的值进行验证。如果验证失败,则抛出异常。可以通过将
spark.sql.sources.validatePartitionColumns设置为false来禁用此类验证。 -
在Spark 3.0中,如果在递归目录列表期间(即,在中间列表中出现,但在后续阶段无法读取或列出的情况下,由于并发文件删除或对象存储一致性问题)文件或子目录消失,则列表将失败并抛出异常,除非
spark.sql.files.ignoreMissingFiles设置为true(默认为false)。在之前的版本中,这些缺失的文件或子目录将被忽略。请注意,此更改的行为仅适用于初始表文件列表(或REFRESH TABLE期间),而不是在查询执行期间:净变化是现在在表文件列表/查询计划期间遵守spark.sql.files.ignoreMissingFiles,而不仅仅在查询执行时。 -
在Spark 2.4及以下版本中,JSON数据源的解析器将空字符串视为某些数据类型(如
IntegerType)的null值。对于FloatType、DoubleType、DateType和TimestampType,它会在遇到空字符串时失败并抛出异常。Spark 3.0不允许空字符串,并且除了StringType和BinaryType之外的数据类型都会抛出异常。可以将spark.sql.legacy.json.allowEmptyString.enabled设置为true来恢复先前允许空字符串的行为。 -
在Spark 2.4及以下版本中,JSON数据源和
from_json等JSON函数在StructType模式下将错误的JSON记录转换为所有字段均为null的行(在PERMISSIVE模式下)。在Spark 3.0中,如果某些JSON列值被成功解析和转换为所需类型,则返回的行可以包含非null字段。 -
在Spark 3.0中,JSON数据源和
schema_of_json函数从字符串值推断TimestampType类型,如果它们与JSON选项timestampFormat定义的模式匹配。将JSON选项inferTimestamp设置为false以禁用此类类型推断。 -
在Spark 2.4及以下版本中,CSV数据源在PERMISSIVE模式下将格式错误的CSV字符串转换为所有字段均为null的行。在Spark 3.0中,如果某些CSV列值被成功解析和转换为所需类型,则返回的行可以包含非null字段。
-
在Spark 3.0中,使用用户提供的模式写入Avro文件时,字段将根据Catalyst模式和Avro模式之间的字段名进行匹配,而不是位置。
-
在Spark 3.0中,使用用户提供的非空模式写入Avro文件时,即使Catalyst模式可为空,Spark仍然能够写入文件。但是,如果任何记录包含null,则Spark会抛出运行时NullPointerException。
其他变化
-
在Spark 2.4中,通过
cloneSession()创建Spark会话时,新创建的Spark会话继承其父SparkContext的配置,即使相同的配置在父Spark会话中具有不同的值。在Spark 3.0中,父SparkSession的配置优先于父SparkContext。可以通过将spark.sql.legacy.sessionInitWithConfigDefaults设置为true来恢复旧的行为。 -
在Spark 3.0中,如果在
Spark SQL配置中找不到hive.default.fileformat,则会回退到SparkContext的Hadoop配置中存在的hive-site.xml文件。 -
在Spark 3.0中,我们对
spark-sql接口中的十进制数进行尾部零填充,以与列的精度保持一致,例如:查询 Spark 2.4 Spark 3.0 SELECT CAST(1 AS decimal(38, 18));1 1.000000000000000000 -
在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进行脚本转换时,Hive 1.2和Hive 2.3之间的字符串表示可能不同,具体取决于hive的行为。在Hive 1.2中,字符串表示省略尾随零。但在Hive 2.3中,如果需要,它总是填充为18位数字,并包含尾随零。
-
本文详细介绍了从Spark SQL 2.4升级到3.0的多方面变化,包括Dataset/DataFrame API、DDL语句、UDF和内置函数、查询引擎、数据源等。如在API方面,分组属性命名改变;DDL语句中类型转换遵循ANSI标准等,还给出了恢复旧行为的配置方法。
1673

被折叠的 条评论
为什么被折叠?



