共用方式為


使用者定義的純量函式 - Scala

本文包含 Scala 使用者定義函式 (UDF) 範例。 本文示範如何註冊 UDF、如何叫用 UDF,以及有關 Spark SQL 中子運算式評估順序的警告。 如需詳細資訊,請參閱外部使用者定義純量函式 (UDF)

注意

在已啟用 Unity 目錄的計算資源上使用共用存取模式的 Scala UDF 需要 Databricks Runtime 14.2 和更新版本。

將函式註冊為 UDF

val squared = (s: Long) => {
  s * s
}
spark.udf.register("square", squared)

在 Spark SQL 中呼叫 UDF

spark.range(1, 20).createOrReplaceTempView("test")
%sql select id, square(id) as id_squared from test

搭配 DataFrame 使用 UDF

import org.apache.spark.sql.functions.{col, udf}
val squared = udf((s: Long) => s * s)
display(spark.range(1, 20).select(squared(col("id")) as "id_squared"))

評估順序和 Null 檢查

Spark SQL (包括 SQL 和 DataFrame 和資料集 API) 不保證子運算式的評估順序。 特別是,運算子或函式的輸入不一定以左至右或任何其他固定順序進行評估。 例如,邏輯 ANDOR 運算式沒有由左至右的「短路」語意。

因此,依賴布林運算式評估的副作用或順序,以及 WHEREHAVING 子句的順序是危險的做法,因為這類運算式和子句可以在查詢最佳化和規劃期間重新排序。 具體來說,如果 UDF 依賴 SQL 中的短路語意進行 Null 檢查,則不保證在叫用 UDF 之前會發生 Null 檢查。 例如,

spark.udf.register("strlen", (s: String) => s.length)
spark.sql("select s from test1 where s is not null and strlen(s) > 1") // no guarantee

WHERE 子句不保證在篩選出 Null 之後叫用 strlen UDF。

若要執行適當的 Null 檢查,建議您執行下列其中一項:

  • 讓 UDF 本身成為 Null 感知,並在 UDF 本身內執行 Null 檢查
  • 使用 IFCASE WHEN 運算式執行 Null 檢查,並在條件分支中叫用 UDF
spark.udf.register("strlen_nullsafe", (s: String) => if (s != null) s.length else -1)
spark.sql("select s from test1 where s is not null and strlen_nullsafe(s) > 1") // ok
spark.sql("select s from test1 where if(s is not null, strlen(s), null) > 1")   // ok

具類型的資料集 API

注意

此功能在 Databricks Runtime 15.4 及以上版本中支援共享存取模式的 Unity 目錄叢集上受支援。

具類型的資料集 API 可讓您使用使用者定義的函數,在產生的資料集上執行轉換,例如地圖、篩選和匯總。

例如,下列 Scala 應用程式會使用 map() API 將結果資料行中的數字修改為前置字串。

spark.range(3).map(f => s"row-$f").show()

雖然此範例使用 map() API,但這也適用於其他具類型的資料集 API,例如 filter()mapPartitions()foreach()foreachPartition()reduce()flatMap()