很容易判断您是否检查了执行计划:
scala> df.select(squareUDF($"name")).explain(true)
== Parsed Logical Plan ==
'Project [UDF('name) AS UDF(name)#51]
+- AnalysisBarrier Project [value#36 AS name#38]
== Analyzed Logical Plan ==
UDF(name): double
Project [if (isnull(cast(name#38 as double))) null else UDF(cast(name#38 as double)) AS UDF(name)#51]
+- Project [value#36 AS name#38]
+- LocalRelation [value#36]
== Optimized Logical Plan ==
LocalRelation [UDF(name)#51]
== Physical Plan ==
LocalTableScan [UDF(name)#51]
如您所见,Spark在应用UDF之前执行类型转换:
UDF(cast(name#38 as double))
SQL强制转换不会为类型兼容的强制转换引发异常。如果无法进行实际转换,则值未定义(
NULL
). 如果类型不兼容:
Seq((1, ("Raphael", 42))).toDF("id", "name_number").select(squareUDF($"name_number"))
// org.apache.spark.sql.AnalysisException: cannot resolve 'UDF(name_number)' due to data type mismatch: argument 1 requires double type, however, '`name_number`' is of struct<_1:string,_2:int> type.;;
//
// at org.apache...
你会得到一个例外。
如果类型不兼容
其余部分包括:
if (isnull(cast(name#38 as double))) null
因为值为
null
从未调用udf。