gpt4 book ai didi

scala - 什么是无类型 Scala UDF 和有类型 Scala UDF?它们的区别是什么?

转载 作者:行者123 更新时间:2023-12-03 23:42:11 28 4
gpt4 key购买 nike

我已经使用 Spark 2.4 一段时间了,最​​近几天才开始切换到 Spark 3.0。切换到 Spark 3.0 运行后出现此错误 udf((x: Int) => x, IntegerType) :

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 迁移指南页面:

In Spark 3.0, using org.apache.spark.sql.functions.udf(AnyRef, DataType) is not allowed by default. Remove the return type parameter to automatically switch to typed Scala udf is recommended, or set spark.sql.legacy.allowUntypedScalaUDF to true to keep using it. In Spark version 2.4 and below, if org.apache.spark.sql.functions.udf(AnyRef, DataType) gets a Scala closure with primitive-type argument, the returned UDF returns null if the input values is null. However, in Spark 3.0, the UDF returns the default value of the Java type if the input value is null. For example, val f = udf((x: Int) => x, IntegerType), f($"x") returns null in Spark 2.4 and below if column x is null, and return 0 in Spark 3.0. This behavior change is introduced because Spark 3.0 is built with Scala 2.12 by default.

source: Spark Migration Guide


我注意到我通常的使用方式 function.udf API,即 udf(AnyRef, DataType) ,被称为 UnTyped Scala UDF以及建议的解决方案,即 udf(AnyRef) ,被称为 Typed Scala UDF .
  • 根据我的理解,第一个看起来比第二个更严格的类型,其中第一个明确定义了其输出类型而第二个没有,因此我对为什么它被称为 UnTyped 感到困惑。
  • 该函数也被传递给 udf , 即 (x:Int) => x ,显然已定义其输入类型,但 Spark 声称 You're using untyped Scala UDF, which does not have the input type information ?

  • 我的理解正确吗?即使经过更深入的搜索,我仍然找不到任何 Material 来解释什么是 UnTyped Scala UDF 以及什么是 Typed Scala UDF。
    所以我的问题是:它们是什么?它们的区别是什么?

    最佳答案

    在类型化 Scala UDF 中,UDF 知道作为参数传递的列的类型,而在非类型化 Scala UDF 中,UDF 不知道作为参数传递的列的类型
    创建类型化 scala UDF 时,作为参数传递的列类型和 UDF 的输出是从函数参数和输出类型推断出来的,而在创建非类型化 scala UDF 时,根本没有类型推断,无论是参数还是输出。
    令人困惑的是,在创建类型化 UDF 时,类型是从函数推断出来的,而不是作为参数显式传递的。更明确地说,您可以按如下方式编写类型化 UDF 创建:

    val my_typed_udf = udf[Int, Int]((x: Int) => Int)
    现在,让我们看看你提出的两点。

    To my understanding, the first one (eg udf(AnyRef, DataType)) looks more strictly typed than the second one (eg udf(AnyRef)) where the first one has its output type explicitly defined and the second one does not, hence my confusion on why it's called UnTyped.


    根据 spark functions scaladoc , 签名 udf对于第一个函数,将函数转换为 UDF 的函数实际上是:
    def udf(f: AnyRef, dataType: DataType): UserDefinedFunction 
    对于第二个:
    def udf[RT: TypeTag, A1: TypeTag](f: Function1[A1, RT]): UserDefinedFunction
    所以第二个实际上比第一个更类型化,因为第二个考虑了作为参数传递的函数的类型,而第一个删除了函数的类型。
    这就是为什么在第一个你需要定义返回类型,因为 spark 需要这个信息,但不能从作为参数传递的函数推断它,因为它的返回类型被删除,而在第二个中,返回类型是从作为参数传递的函数推断出来的争论。

    Also the function got passed to udf, which is (x:Int) => x, clearly has its input type defined but Spark claiming You're using untyped Scala UDF, which does not have the input type information?


    这里重要的不是函数,而是 Spark 如何从这个函数创建 UDF。
    在这两种情况下,要转换为 UDF 的函数都定义了其输入和返回类型,但是在使用 udf(AnyRef, DataType) 创建 UDF 时,这些类型会被删除并且不会被考虑在内。 .

    关于scala - 什么是无类型 Scala UDF 和有类型 Scala UDF?它们的区别是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65121888/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com