当前位置: 首页 > 知识库问答 >
问题:

什么是非类型化的Scala UDF和类型化的Scala UDF?他们的区别是什么?

弓宏茂
2023-03-14

我已经使用Spark 2.4一段时间了,最近几天刚开始切换到Spark 3.0。在切换到Spark 3.0运行<code>udf((x:Int)之后,我得到了这个错误=

Caused by: org.apache.spark.sql.AnalysisException: You're using untyped Scala UDF, which does not have the input type information. Spark may blindly pass null to the Scala closure with primitive-type argument, and the closure will see the default value of the Java type for the null argument, e.g. `udf((x: Int) => x, IntegerType)`, the result is 0 for null input. To get rid of this error, you could:
1. use typed Scala UDF APIs(without return type parameter), e.g. `udf((x: Int) => x)`
2. use Java UDF APIs, e.g. `udf(new UDF1[String, Integer] { override def call(s: String): Integer = s.length() }, IntegerType)`, if input types are all non primitive
3. set spark.sql.legacy.allowUntypedScalaUDF to true and use this API with caution;

这些解决方案是由Spark自己提出的,在搜索了一段时间后,我进入了Spark迁移指南页面:

在Spark 3.0中,默认情况下不允许使用org.apache.spark.sql.functions.udf(AnyRef, DataType)。建议删除返回类型参数以自动切换到类型化的Scala udf,或将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类型的默认值。例如,val f=udf((x: Int)=

来源:Spark迁移指南

我注意到我通常使用< code>function.udf API的方式,即< code>udf(AnyRef,DataType),被称为< code >非类型化Scala UDF,而建议的解决方案,即< code>udf(AnyRef),被称为< code >类型化Scala UDF。

  • 根据我的理解,第一个看起来比第二个类型更严格,第一个具有显式定义的输出类型,而第二个则没有,因此我对为什么它被称为UnTyped感到困惑。
  • 此外,该函数被传递给 udf,即 (x:Int) =

我的理解正确吗?即使经过更深入的搜索,我仍然找不到任何资料来解释什么是非类型化的Scala UDF,什么是类型化的Scala UDF。

所以我的问题是:它们是什么?它们有什么不同?


共有2个答案

蒋培
2023-03-14

这并没有回答您最初提出的不同UDF是什么的问题,但是如果您想消除这个错误,在Python中,您可以在脚本中包含这一行:< code > spark . SQL(" set spark . SQL . legacy . allowuntypedscalaudf = true ")。

金英华
2023-03-14
匿名用户

在类型化 scala UDF 中,UDF 知道作为参数传递的列的类型,而在非类型化 scala UDF 中,UDF 不知道作为参数传递的列的类型

在创建类型化scala UDF时,作为参数传递的列类型和UDF的输出是从函数参数和输出类型推断出来的,而在创建非类型化的scala UDF时,无论是参数还是输出,都没有类型推断。

可能令人困惑的是,在创建类型化UDF时,类型是从函数推断出来的,而不是显式作为参数传递。更明确地说,您可以将类型化UDF创建编写如下:

val my_typed_udf = udf[Int, Int]((x: Int) => Int)

现在,让我们看看你提出的两点。

据我了解,第一个(例如udf(AnyRef, DataType))看起来比第二个(例如udf(AnyRef))更严格地类型化,其中第一个显式定义了其输出类型,而第二个没有,因此我对为什么它被称为UnTyed感到困惑。

根据spark functions scaladoc,将函数转换为udf的< code>udf函数的签名实际上是,对于第一个函数:

def udf(f: AnyRef, dataType: DataType): UserDefinedFunction 

对于第二个:

def udf[RT: TypeTag, A1: TypeTag](f: Function1[A1, RT]): UserDefinedFunction

所以第二个实际上比第一个更有类型,因为第二个考虑了作为参数传递的函数的类型,而第一个删除了函数的类型。

这就是为什么在第一个例子中需要定义返回类型,因为spark需要这个信息,但是不能从作为参数传递的函数中推断出来,因为它的返回类型被删除了,而在第二个例子中,返回类型是从作为参数传递的函数中推断出来的。

此外,该函数被传递到<code>udf<code>中,即<code>(x:Int)=

这里重要的不是函数,而是 Spark 如何从此函数创建 UDF。

在这两种情况下,要转换为UDF的函数都定义了其输入和返回类型,但在使用UDF(AnyRef,DataType)创建UDF时,这些类型将被删除,并且不考虑。

 类似资料:
  • 和之间的区别是什么? 上述结果如下: “Point”仅指类型,但在此处用作值。 为什么会这样呢?我肯定不会使用作为值,而是使用它来实例化类型。 在哪些情况下,我需要使用,因为不合适?

  • 这两条线有什么区别 和 或者

  • 问题内容: 该链接指出以下内容: 具有实际类型参数的泛型类型的实例化称为参数化类型。示例(参数化类型): 那么什么是参数化类型? 要么 问题答案: 它们都是参数化类型:以其他类型为参数的类型。 您在表达式的两侧具有不同类型的事实是无关紧要的,并且与多态行为有关,即因为是的子类型。

  • 问题内容: 嗨,我在我的经验中都使用了这两种方法,而我当时在想方法和类型都是 POST 和 GET 方法。 但是似乎它们并不相似。 如果我使用它正在工作,我是一个表格数据。 如果我写它不起作用,谁能解释他们之间的区别是什么..? 帮助是适当的。 问题答案: 类型(默认:’GET’)类型:字符串方法的别名。 如果您使用的是1.9.0之前的jQuery版本, 则应使用 type。 http://api

  • 使用指南 - 统计设置 - 转化设置 - 什么是转化及统计支持的转化类型 转化是指用户在您网站上完成的某项给您带来收益的活动,如购买、注册、留言咨询等,当用户达成一次您设定的目标,算作完成一次转化。提高转化率是提高网站投资回报率的最快方法,转化率提升1%意味着网站的运营更高效,会给公司的情况带来戏剧性的变化。 网站的转化可能是多方面的,并会随着公司发展而不断调整,常见的业务目标举例如下: 获取客户

  • 本文向大家介绍写出js各类型转化为Boolean的值分别是什么?及转化的规则是什么?相关面试题,主要包含被问及写出js各类型转化为Boolean的值分别是什么?及转化的规则是什么?时的应答技巧和注意事项,需要的朋友参考一下 类型 值 Number 除和以外为 String 非空为 Boolean 为 Undefined Null Object 除以外为 Function Symbol BigInt