Vad är användardefinierade funktioner (UDF:er)?
Med användardefinierade funktioner (UDF:er) kan du återanvända och dela kod som utökar inbyggda funktioner i Azure Databricks. Använd UDF:er för att utföra specifika uppgifter, till exempel komplexa beräkningar, transformeringar eller anpassade datamanipuleringar.
Kommentar
I kluster med läget för delad åtkomst stöds python-skalära UDF:er i Databricks Runtime 13.3 LTS och senare, medan Scala UDF:er stöds i Databricks Runtime 14.2 och senare.
Python-skalära UDF:er kan registreras i Unity Catalog med sql-syntax i Databricks Runtime 13.3 LTS och senare. Se Användardefinierade funktioner (UDF: er) i Unity Catalog.
När ska du använda en UDF?
Använd UDF:er för logik som är svår att uttrycka med inbyggda Apache Spark-funktioner. Inbyggda Apache Spark-funktioner är optimerade för distribuerad bearbetning och erbjuder i allmänhet bättre prestanda i stor skala. Mer information finns i Funktioner.
Databricks rekommenderar UDF:er för ad hoc-frågor, manuell datarensning, undersökande dataanalys och åtgärder på små till medelstora datamängder. Vanliga användningsfall för UDF:er är datakryptering och dekryptering, hashning, JSON-parsning och validering.
Använd Apache Spark-metoder för åtgärder på mycket stora datauppsättningar och alla arbetsbelastningar som körs regelbundet eller kontinuerligt, inklusive ETL-jobb och strömningsåtgärder.
Registrerade och sessionsomfångade UDF:er
UDF:er som skapats med SQL är registrerade i Unity Catalog och har associerade behörigheter, medan UDF:er som skapats i din notebook-fil är sessionsbaserade och är begränsade till den aktuella SparkSession.
Du kan definiera och komma åt sessionsbaserade UDF:er med valfritt språk som stöds av Azure Databricks. UDF:er kan vara skalära eller icke-skalära.
Kommentar
För närvarande är endast SQL- och Python-skalära UDF:er registrerade i Unity Catalog tillgängliga i DBSQL.
Skalära UDF:er
Skalära UDF:er fungerar på en enskild rad och returnerar ett enda värde för varje rad. I följande exempel används en skalär UDF för att beräkna längden på varje namn i en name
kolumn och lägga till värdet i en ny kolumn name_length
:
+-------+-------+
| name | score |
+-------+-------+
| alice | 10.0 |
| bob | 20.0 |
| carol | 30.0 |
| dave | 40.0 |
| eve | 50.0 |
+-------+-------+
-- Create a SQL UDF for name length
CREATE OR REPLACE FUNCTION get_name_length(name STRING)
RETURNS INT
RETURN LENGTH(name);
-- Use the UDF in a SQL query
SELECT name, get_name_length(name) AS name_length
FROM your_table;
+-------+-------+-------------+
| name | score | name_length |
+-------+-------+-------------+
| alice | 10.0 | 5 |
| bob | 20.0 | 3 |
| carol | 30.0 | 5 |
| dave | 40.0 | 4 |
| eve | 50.0 | 3 |
+-------+-------+-------------+
Så här implementerar du detta i en Databricks-notebook-fil med PySpark:
from pyspark.sql.functions import udf
from pyspark.sql.types import IntegerType
@udf(returnType=IntegerType())
def get_name_length(name):
return len(name)
df = df.withColumn("name_length", get_name_length(df.name))
# Show the result
display(df)
Mer information finns i Användardefinierade funktioner (UDF: er) i Unity Catalog och Användardefinierade skalärfunktioner – Python.
Användardefinierade sammansättningsfunktioner (UDAF)
Användardefinierade aggregeringsfunktioner (UDAF:er) fungerar på flera rader och returnerar ett enda aggregerat resultat. I följande exempel definieras en UDAF som aggregerar poäng.
from pyspark.sql.functions import pandas_udf
from pyspark.sql import SparkSession
import pandas as pd
# Define a pandas UDF for aggregating scores
@pandas_udf("int")
def total_score_udf(scores: pd.Series) -> int:
return scores.sum()
# Group by name length and aggregate
result_df = (df.groupBy("name_length")
.agg(total_score_udf(df["score"]).alias("total_score")))
display(result_df)
+-------------+-------------+
| name_length | total_score |
+-------------+-------------+
| 3 | 70.0 |
| 4 | 40.0 |
| 5 | 40.0 |
+-------------+-------------+
Se användardefinierade funktioner för Pandas för Python- och användardefinierade aggregeringsfunktioner – Scala.
Användardefinierade python-tabellfunktioner (UDF: er)
Viktigt!
Den här funktionen finns som allmänt tillgänglig förhandsversion.
Kommentar
Python-UDF:er är tillgängliga i Databricks Runtime 14.3 LTS och senare.
Användardefinierade python-tabellfunktioner (UDF: er) kan returnera flera rader och kolumner för varje indatarad. I följande exempel motsvarar varje värde i poängkolumnen en lista med kategorier. En UDTF definieras för att dela upp kommaavgränsad lista i flera rader. Se Användardefinierade tabellfunktioner i Python (UDF)
+-------+-------+-----------------+
| name | score | categories |
+-------+-------+-----------------+
| alice | 10.0 | math,science |
| bob | 20.0 | history,math |
| carol | 30.0 | science,history |
| dave | 40.0 | math,art |
| eve | 50.0 | science,art |
+-------+-------+-----------------+
from pyspark.sql.functions import udtf
@udtf(returnType="score: int, categories: string, name: string")
class ScoreCategoriesUDTF:
def eval(self, name: str, score: float, categories: str):
category_list = categories.split(',')
for category in category_list:
yield (name, score, category)
# Apply the UDTF
result_df = df.select(ScoreCategoriesUDTF(df.score, df.categories, df.name))
display(result_df)
+-------+-------+----------+
| name | score | category |
+-------+-------+----------+
| alice | 10.0 | math |
| alice | 10.0 | science |
| bob | 20.0 | history |
| bob | 20.0 | math |
| carol | 30.0 | science |
| carol | 30.0 | history |
| dave | 40.0 | math |
| dave | 40.0 | art |
| eve | 50.0 | science |
| eve | 50.0 | art |
+-------+-------+----------+
Prestandaöverväganden
- Inbyggda funktioner och SQL UDF:er är det mest effektiva alternativet som är tillgängligt.
- Scala-UDF:er är vanligtvis snabbare när de körs i den virtuella Java-datorn (JVM) och undviker att flytta data in och ut ur JVM.
- Python UDF:er och Pandas UDF:er tenderar att vara långsammare än Scala UDF:er eftersom de kräver att data serialiseras och flyttas från JVM till Python-tolken. Pandas UDF:er upp till 100 x snabbare än Python-UDF:er eftersom de använder Apache Arrow för att minska serialiseringskostnaderna.