Share via


O que são funções definidas pelo usuário (UDFs)?

Uma função definida pelo usuário (UDF) é uma função definida por um usuário, permitindo que a lógica personalizada seja reutilizada no ambiente do usuário. O Azure Databricks tem suporte para muitos tipos diferentes de UDFs para permitir a distribuição de lógica extensível. Este artigo apresenta alguns dos pontos fortes e limitações gerais das UDF.

Nota

Nem todas as formas de UDFs estão disponíveis em todos os ambientes de execução no Azure Databricks. Se você estiver trabalhando com o Unity Catalog, consulte User-defined functions (UDFs) no Unity Catalog.

Consulte os seguintes artigos para obter mais informações sobre UDFs:

Definindo lógica personalizada sem penalidades de serialização

O Azure Databricks herda grande parte de seus comportamentos UDF do Apache Spark, incluindo as limitações de eficiência em torno de muitos tipos de UDFs. Consulte Quais UDFs são mais eficientes?.

Você pode modularizar seu código com segurança sem se preocupar com possíveis compensações de eficiência associadas a UDFs. Para fazer isso, você deve definir sua lógica como uma série de métodos internos do Spark usando SQL ou Spark DataFrames. Por exemplo, as seguintes funções SQL e Python combinam métodos internos do Spark para definir uma conversão de unidade como uma função reutilizável:

SQL

CREATE FUNCTION convert_f_to_c(unit STRING, temp DOUBLE)
RETURNS DOUBLE
RETURN CASE
  WHEN unit = "F" THEN (temp - 32) * (5/9)
  ELSE temp
END;

SELECT convert_f_to_c(unit, temp) AS c_temp
FROM tv_temp;

Python

def convertFtoC(unitCol, tempCol):
  from pyspark.sql.functions import when
  return when(unitCol == "F", (tempCol - 32) * (5/9)).otherwise(tempCol)

from pyspark.sql.functions import col

df_query = df.select(convertFtoC(col("unit"), col("temp"))).toDF("c_temp")
display(df_query)

Para executar as UDFs acima, você pode criar dados de exemplo.

Quais UDFs são mais eficientes?

As UDFs podem introduzir gargalos de processamento significativos na execução do código. O Azure Databricks usa vários otimizadores diferentes automaticamente para código escrito com sintaxe Apache Spark, SQL e Delta Lake incluída. Quando a lógica personalizada é introduzida por UDFs, esses otimizadores não têm a capacidade de planejar eficientemente tarefas em torno dessa lógica personalizada. Além disso, a lógica que é executada fora da JVM tem custos adicionais em torno da serialização de dados.

Nota

O Azure Databricks otimiza muitas funções usando Photon se você usar computação habilitada para Photon. Somente funções que encadeiam comandos do Spark SQL do DataFrame podem ser otimizadas pelo Photon.

Algumas FDU são mais eficientes do que outras. Em termos de desempenho:

  • As funções incorporadas serão mais rápidas devido aos otimizadores do Azure Databricks.
  • O código executado na JVM (UDFs Scala, Java, Hive) será mais rápido do que UDFs do Python.
  • Pandas UDFs usam Arrow para reduzir os custos de serialização associados com Python UDFs.
  • UDFs Python funcionam bem para lógica processual, mas devem ser evitados para cargas de trabalho ETL de produção em grandes conjuntos de dados.

Nota

No Databricks Runtime 12.2 LTS e inferior, UDFs escalares Python e UDFs Pandas não são suportados no Unity Catalog em clusters que usam o modo de acesso compartilhado. Essas UDFs são suportadas no Databricks Runtime 13.3 LTS e acima para todos os modos de acesso.

No Databricks Runtime 14.1 e inferior, UDFs escalares Scala não são suportados no Unity Catalog em clusters que usam o modo de acesso compartilhado. Essas UDFs são suportadas para todos os modos de acesso no Databricks Runtime 14.2 e superior.

No Databricks Runtime 13.3 LTS e superior, você pode registrar UDFs Python escalares no Unity Catalog usando sintaxe SQL. Consulte Funções definidas pelo usuário (UDFs) no Catálogo Unity.

Type Otimizado Ambiente de execução
Colmeia UDF Não JVM
Python UDF Não Python
Pandas UDF Não Python (Seta)
Scala UDF Não JVM
SQL do Apache Spark Sim JVM (Fóton)
Spark DataFrame Sim JVM (Fóton)

Quando se deve usar um UDF?

Um grande benefício dos UDFs é que eles permitem que os usuários expressem lógica em linguagens familiares, reduzindo o custo humano associado à refatoração de código. Para consultas ad hoc, limpeza manual de dados, análise exploratória de dados e a maioria das operações em conjuntos de dados de pequeno ou médio porte, é improvável que os custos gerais de latência associados a UDFs superem os custos associados ao código de refatoração.

Para trabalhos de ETL, operações de streaming, operações em conjuntos de dados muito grandes ou outras cargas de trabalho que são executadas regularmente ou continuamente, a lógica de refatoração para usar métodos nativos do Apache Spark paga dividendos rapidamente.

Dados de exemplo, por exemplo, UDFs

Os exemplos de código neste artigo usam UDFs para converter temperaturas entre Celcius e Farenheit. Se desejar executar essas funções, você pode criar um conjunto de dados de exemplo com o seguinte código Python:

import numpy as np
import pandas as pd

Fdf = pd.DataFrame(np.random.normal(55, 25, 10000000), columns=["temp"])
Fdf["unit"] = "F"

Cdf = pd.DataFrame(np.random.normal(10, 10, 10000000), columns=["temp"])
Cdf["unit"] = "C"

df = spark.createDataFrame(pd.concat([Fdf, Cdf]).sample(frac=1))

df.cache().count()
df.createOrReplaceTempView("tv_temp")