Sdílet prostřednictvím


Skalární funkce definované uživatelem – Scala

Tento článek obsahuje příklady uživatelem definované funkce Scala (UDF). Ukazuje, jak zaregistrovat funkce definované uživatelem, jak vyvolat funkce definované uživatelem a upozadět v souvislosti s pořadím vyhodnocení dílčích výrazů ve Spark SQL. Další podrobnosti najdete v tématu Externí uživatelem definované skalární funkce (UDF ).

Uživatelem definované funkce Scala ve výpočetních prostředcích s podporou katalogu Unity s režimem sdíleného přístupu vyžaduje Databricks Runtime 14.2 a vyšší.

Registrace funkce jako funkce definované uživatelem

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

Volání funkce definovaná uživatelem ve Spark SQL

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

Použití UDF s datovými rámci

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"))

Kontrola pořadí vyhodnocení a hodnoty null

Spark SQL (včetně rozhraní SQL a rozhraní API datových rámců a datových sad) nezaručuje pořadí vyhodnocení dílčích výrazů. Zejména vstupy operátoru nebo funkce nejsou nutně vyhodnoceny zleva doprava nebo v jiném pevném pořadí. Například logické AND výrazy OR nemají sémantiku "zkratování" zleva doprava.

Proto je nebezpečné spoléhat se na vedlejší účinky nebo pořadí vyhodnocení logických výrazů a pořadí WHERE HAVING a pořadí klauzulí, protože tyto výrazy a klauzule je možné změnit pořadí během optimalizace a plánování dotazů. Konkrétně platí, že pokud UDF spoléhá na sémantiku zkratování v SQL pro kontrolu hodnoty null, neexistuje žádná záruka, že se kontrola hodnoty null provede před vyvoláním funkce definované uživatelem. Příklad:

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

Tato WHERE klauzule nezaručuje, že se funkce definovaná uživatelem strlen bude volat po vyfiltrování hodnot null.

Pokud chcete provést správnou kontrolu hodnoty null, doporučujeme provést některou z následujících akcí:

  • Nastavení samotné funkce definovaná uživatelem s podporou hodnoty null a provedení kontroly hodnoty null uvnitř samotného uživatelem definovaného uživatelem
  • Použití IF nebo CASE WHEN výrazy k ověření hodnoty null a vyvolání funkce definovaná uživatelem v podmíněné větvi
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

Typed Dataset APIs

Poznámka:

Tato funkce je podporována v clusterech s podporou katalogu Unity s režimem sdíleného přístupu v Databricks Runtime 15.4 a novějším.

Rozhraní API typové datové sady umožňují spouštět transformace, jako je mapování, filtrování a agregace u výsledných datových sad s uživatelem definovanou funkcí.

Například následující aplikace Scala používá map() rozhraní API k úpravě čísla ve výsledném sloupci na předponu řetězce.

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

I když tento příklad používá map() rozhraní API, platí to také pro jiná typovaná rozhraní API datové sady, jako filter()jsou , mapPartitions(), foreach(), , foreachPartition()reduce()a flatMap().