Pular para o conteúdo principal

Funções escalares definidas pelo usuário - Scala

Este artigo contém Scala exemplos de funções definidas pelo usuário (UDF). Ele mostra como registrar UDFs, como invocar UDFs e advertências sobre a ordem de avaliação de subexpressões em Spark SQL. Consulte Funções escalares externas definidas pelo usuário (UDFs) para obter mais detalhes.

nota

Scala UDFs no Unity Catalog habilitado compute recurso com modo de acesso padrão (anteriormente modo de acesso compartilhado) requer Databricks Runtime 14.2 e acima.

Graviton O suporte de instância para Scala UDFs no clustering habilitado para o Unity Catalog está disponível em Databricks Runtime 15.2 e acima.

registrar uma função como um UDF

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

Chamar o UDF no Spark SQL

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

Usar UDF com DataFrames

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

Ordem de avaliação e verificação de nulos

Spark SQL (incluindo SQL e DataFrame e o conjunto de dados APIs) não garante a ordem de avaliação das subexpressões. Em particular, as entradas de um operador ou função não são necessariamente avaliadas da esquerda para a direita ou em qualquer outra ordem fixa. Por exemplo, as expressões lógicas AND e OR não têm semântica de “curto-circuito” da esquerda para a direita.

Portanto, é perigoso confiar nos efeitos colaterais ou na ordem de avaliação das expressões Boolean e na ordem das cláusulas WHERE e HAVING, pois essas expressões e cláusulas podem ser reordenadas durante a otimização e o planejamento da consulta. Especificamente, se um UDF depender da semântica de curto-circuito no SQL para verificação de nulidade, não há garantia de que a verificação de nulidade ocorrerá antes de invocar o UDF. Por exemplo,

Scala
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

Essa cláusula WHERE não garante que o UDF strlen seja invocado após a filtragem de nulos.

Para realizar uma verificação de nulo adequada, recomendamos que você faça o seguinte:

  • Tornar o próprio UDF sensível a nulidade e fazer a verificação de nulidade dentro do próprio UDF
  • Use as expressões IF ou CASE WHEN para fazer a verificação de nulidade e chamar o UDF em uma ramificação condicional
Scala
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

Conjunto de dados digitados APIs

nota

Esse recurso é suportado no clustering habilitado para o Unity Catalog com modo de acesso padrão em Databricks Runtime 15.4 e acima.

Conjunto de dados digitado APIs permite a execução de transformações como mapa, filtro e agregações no conjunto de dados resultante com uma função definida pelo usuário.

Por exemplo, o aplicativo Scala a seguir usa o map() API para modificar um número em uma coluna de resultados para uma cadeia de caracteres prefixada.

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

Embora este exemplo use o map() API, isso também se aplica a outros conjuntos de dados digitados APIs, como filter(), mapPartitions(), foreach(), foreachPartition(), reduce() e flatMap().