Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Python scalar UDF pozwala uruchamiać niestandardową logikę Python w zapytaniach SQL na Azure Databricks. Ta strona pokazuje, jak je rejestrować i wywoływać, korzystać z poświadczeń i sekretów usług oraz obsługiwać zastrzeżenia w kolejności oceny podwyrazów w SQL Spark.
Requirements
W środowisku Databricks Runtime 12.2 LTS i starszym funkcje zdefiniowane przez użytkownika języka Python i funkcje zdefiniowane przez użytkownika biblioteki Pandas nie są obsługiwane w obliczeniach na Unity Catalog, które korzystają z trybu standardowego dostępu.
Skalarne funkcje zdefiniowane przez użytkownika w Pythonie (UDF) i funkcje zdefiniowane przez użytkownika w Pandas (UDF) są obsługiwane w Databricks Runtime 13.3 LTS i nowszych wersjach dla wszystkich trybów dostępu.
Obsługa instancji ARM dla funkcji UDF języka Python w klastrach z włączonym Unity Catalog wymaga środowiska Databricks Runtime 15.2 lub nowszego.
W środowisku Databricks Runtime 14.0 i wcześniejszym funkcje zdefiniowane przez użytkownika w języku Python i funkcje zdefiniowane przez użytkownika w bibliotece Pandas nie są obsługiwane w klastrach Unity Catalog korzystających ze standardowego trybu dostępu. Skalarne funkcje zdefiniowane przez użytkownika w Pythonie i funkcje Pandas zdefiniowane przez użytkownika są obsługiwane dla wszystkich trybów dostępu w systemie Databricks Runtime 14.1 lub nowszym.
W Databricks Runtime 14.1 lub nowszym można zarejestrować skalarne funkcje UDF Pythona w Unity Catalog przy użyciu składni SQL. Zobacz funkcje definiowane przez użytkownika (UDF) w językach SQL i Python w Unity Catalog.
Rejestracja funkcji jako UDF
def squared(s):
return s * s
spark.udf.register("squaredWithPython", squared)
Opcjonalnie można ustawić typ zwracany funkcji zdefiniowanej przez użytkownika. Domyślnym typem zwracania jest StringType.
from pyspark.sql.types import LongType
def squared_typed(s):
return s * s
spark.udf.register("squaredWithPython", squared_typed, LongType())
Wywołaj UDF w Spark SQL
spark.range(1, 20).createOrReplaceTempView("test")
%sql select id, squaredWithPython(id) as id_squared from test
Używanie funkcji UDF z ramkami danych
from pyspark.sql.functions import udf
from pyspark.sql.types import LongType
squared_udf = udf(squared, LongType())
df = spark.table("test")
display(df.select("id", squared_udf("id").alias("id_squared")))
Alternatywnie można zadeklarować tę samą funkcję zdefiniowaną przez użytkownika przy użyciu składni adnotacji:
from pyspark.sql.functions import udf
@udf("long")
def squared_udf(s):
return s * s
df = spark.table("test")
display(df.select("id", squared_udf("id").alias("id_squared")))
Warianty z funkcją UDF
Typ PySpark dla wariantu to VariantType , a wartości są typu VariantVal. Aby uzyskać informacje o wariantach, zobacz Zapytanie dotyczące danych wariantów.
from pyspark.sql.functions import col, lit, udf
from pyspark.sql.types import VariantType, VariantVal
# Return Variant
@udf(returnType = VariantType())
def toVariant(jsonString):
return VariantVal.parseJson(jsonString)
spark.range(1).select(lit('{"a" : 1}').alias("json")).select(toVariant(col("json"))).display()
+---------------+
|toVariant(json)|
+---------------+
| {"a":1}|
+---------------+
from pyspark.sql.functions import col, lit, udf
from pyspark.sql.types import StructField, StructType, VariantType, VariantVal
# Return Struct<Variant>
@udf(returnType = StructType([StructField("v", VariantType(), True)]))
def toStructVariant(jsonString):
return {"v": VariantVal.parseJson(jsonString)}
spark.range(1).select(lit('{"a" : 1}').alias("json")).select(toStructVariant(col("json"))).display()
+---------------------+
|toStructVariant(json)|
+---------------------+
| {"v":{"a":1}}|
+---------------------+
from pyspark.sql.functions import col, lit, udf
from pyspark.sql.types import ArrayType, VariantType, VariantVal
# Return Array<Variant>
@udf(returnType = ArrayType(VariantType()))
def toArrayVariant(jsonString):
return [VariantVal.parseJson(jsonString)]
spark.range(1).select(lit('{"a" : 1}').alias("json")).select(toArrayVariant(col("json"))).display()
+--------------------+
|toArrayVariant(json)|
+--------------------+
| [{"a":1}]|
+--------------------+
from pyspark.sql.functions import col, lit, udf
from pyspark.sql.types import MapType, StringType, VariantType, VariantVal
# Return Map<String, Variant>
@udf(returnType = MapType(StringType(), VariantType(), True))
def toMapVariant(jsonString):
return {"v1": VariantVal.parseJson(jsonString), "v2": VariantVal.parseJson("[" + jsonString + "]")}
spark.range(1).select(lit('{"a" : 1}').alias("json")).select(toMapVariant(col("json"))).display()
+-----------------------------+
| toMapVariant(json)|
+-----------------------------+
|{"v2":[{"a":1}],"v1":{"a":1}}|
+-----------------------------+
Pliki z UDF
Important
Ta funkcja jest dostępna w wersji beta.
Typ PySpark dla pliku to FileType. Użyj go jako parametru lub typu zwracanego w UDF, zarówno jako typu najwyższego poziomu, jak i zagnieżdżonego. Informacje o typie, jego regułach zagnieżdżania oraz interfejsie API FileRef znajdziesz w dokumencie FileType.
Aby odczytać zawartość pliku w UDF, wywołaj file.as_local_file() , aby uzyskać lokalną ścieżkę, którą możesz otworzyć, lub file.open() odczytać jego bajty jako strumień. Przykłady w Python, Scala i SQL, w tym przetwarzanie obrazów, wykrywanie typów plików i ekstrakcję klatek wideo, można znaleźć w artykule Pliki procesowe z UDF. Aby uzyskać informacje o typie, zobacz FILE typ.
UDF zarejestrowany w Unity Catalog (CREATE FUNCTION) może odczytać metadane elementu FILE, ale nie jego zawartość i nie może tworzyć plików. Użyj UDF ograniczonego do sesji do odczytu zawartości pliku (open, as_local_file) lub utworzenia go (from_bytes, from_local_file).
W ciele UDF każda FILE wartość jest obiektem FileRef :
from pyspark.sql.functions import col, udf
from pyspark.sql.types import FileRef, StringType
@udf(returnType=StringType())
def file_content_type(file: FileRef) -> str:
return file.content_type
df = spark.table("documents")
display(df.select(col("file").uri, file_content_type(col("file"))))
Kolejność oceny i sprawdzanie wartości null
Spark SQL (w tym SQL, API DataFrame oraz Dataset) nie gwarantuje kolejności oceny podwyrażeń. W szczególności dane wejściowe operatora lub funkcji nie muszą być oceniane od lewej do prawej ani w innej stałej kolejności. Na przykład wyrażenia logiczne AND i OR nie mają semantyki od lewej do prawej „skrótowego przerywania”.
W związku z tym niebezpieczne jest poleganie na skutkach ubocznych lub kolejności obliczania wyrażeń logicznych oraz kolejności klauzul WHERE i HAVING, ponieważ takie wyrażenia i klauzule mogą zostać zmienione podczas optymalizacji zapytań i planowania. W szczególności, jeśli funkcja UDF wykorzystuje semantykę zwarciową w języku SQL w celu sprawdzania wartości null, nie ma gwarancji, że sprawdzanie wartości null nastąpi przed wywołaniem funkcji UDF. Na przykład:
spark.udf.register("strlen", lambda s: len(s), "int")
spark.sql("select s from test1 where s is not null and strlen(s) > 1") # no guarantee
Ta WHERE klauzula nie gwarantuje, że funkcja zdefiniowana przez użytkownika strlen zostanie wywołana po usunięciu wartości null.
Aby wykonać odpowiednie sprawdzanie wartości null, zalecamy wykonanie jednej z następujących czynności:
- Upewnij się, że funkcja UDF obsługuje wartości null i sprawdza je wewnątrz siebie samej
- Użyj wyrażeń
IFlubCASE WHENdo sprawdzenia braku wartości i wywołania funkcji zdefiniowanej przez użytkownika w gałęzi warunkowej
spark.udf.register("strlen_nullsafe", lambda s: len(s) if not s is None else -1, "int")
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
Uzyskaj dostęp do sekretów katalogu Unity
Aby uzyskać dostęp do sekretu Unity Catalog z funkcji UDF języka Python o zakresie sesji, zobacz Używanie sekretu w funkcji UDF języka Python o zakresie sesji. Aby uzyskać dostęp do zadeklarowanych wpisów tajnych w skalarnej lub wsadowej funkcji UDF języka Python w katalogu Unity Catalog, zobacz Używanie wpisów tajnych w funkcji UDF języka Python.
Dane uwierzytelniające usługi w funkcjach UDF języka Python
Skalarne funkcje UDF języka Python o zakresie sesji oraz skalarne funkcje UDF języka Python w usłudze Unity Catalog mogą używać poświadczeń usługi Unity Catalog do bezpiecznego uzyskiwania dostępu do zewnętrznych usług chmurowych. Jest to przydatne w przypadku integrowania operacji, takich jak tokenizacja w chmurze, szyfrowanie lub zarządzanie tajemnicami bezpośrednio w przekształceniach danych.
Wymagania różnią się w zależności od typu i poziomu obliczeniowego UDF. Zobacz Użyj poświadczenia serwisowego w Python UDF.
Aby utworzyć poświadczenia usługi, zobacz Tworzenie poświadczeń usługi.
Użyj poświadczenia usługi w skalarnym UDF języka Python o zakresie sesji
Aby uzyskać dostęp do poświadczeń usługi, użyj narzędzia databricks.service_credentials.getServiceCredentialsProvider() w logice UDF, aby zainicjować SDK w chmurze odpowiednimi poświadczeniami. Cały kod musi być enkapsulowany w treści funkcji UDF.
@udf
def use_service_credential():
from azure.mgmt.web import WebSiteManagementClient
# Assuming there is a service credential named 'testcred' set up in Unity Catalog
web_client = WebSiteManagementClient(subscription_id, credential = getServiceCredentialsProvider('testcred'))
# Use web_client to perform operations
Uprawnienia poświadczeń usługi
Sesyjne UDF korzystają z uprawnień wywołującego. Zobacz Użyj poświadczenia usługi w Python UDF, aby uzyskać wymagane uprawnienia.
Domyślne poświadczenia na poziomie zasobów obliczeniowych dla funkcji UDF o zakresie sesji
W przypadku skalarnych UDF-ów Python, Databricks automatycznie używa domyślnego poświadczenia usługi ze zmiennej środowiska obliczeniowego. To zachowanie pozwala bezpiecznie odwoływać się do usług zewnętrznych bez jawnego zarządzania aliasami poświadczeń w kodzie UDF. Zobacz Określanie domyślnego poświadczenia usługi dla zasobu obliczeniowego
Domyślna obsługa poświadczeń jest dostępna tylko w klastrach w trybie dostępu standardowym i dedykowanym. Nie jest dostępny w magazynach SQL.
Musisz zainstalować pakiet azure-identity, aby używać dostawcy DefaultAzureCredential. Aby zainstalować pakiet, zobacz Biblioteki Pythona o zakresie notatnika lub Biblioteki o zakresie obliczeniowym.
@udf
def use_service_credential():
from azure.identity import DefaultAzureCredential
from azure.mgmt.web import WebSiteManagementClient
# DefaultAzureCredential is automatically using the default service credential for the compute
web_client_default = WebSiteManagementClient(DefaultAzureCredential(), subscription_id)
# Use web_client to perform operations
Użyj poświadczenia usługi w skalarnym Unity Catalog Python UDF
Określ poświadczenie usługi w klauzuli CREDENTIALS definicji UDF. Możesz oznaczyć jedno poświadczenie jako DEFAULT, aby poprawione chmurowe pakiety SDK automatycznie z niego korzystały. W klasycznym trybie obliczeniowym ta funkcja wymaga Databricks Runtime 18.1 lub nowszego. W środowisku serverless compute oraz w hurtowniach SQL typu pro i serverless jawnie ustaw parametr environment_version funkcji UDF na 6 lub wyższą wartość. Pełne informacje o wymaganiach dotyczących mocy obliczeniowej, sieci i uprawnień znajdziesz w sekcji Korzystanie z poświadczenia usługi w funkcji UDF języka Python.
Pobierz kontekst wykonania zadania
Użyj API PySpark TaskContext, aby uzyskać informacje kontekstowe, takie jak tożsamość użytkownika, tagi klastra, identyfikator zadania Spark i więcej. Zobacz Uzyskiwanie kontekstu zadania w UDF.
Ograniczenia
Następujące ograniczenia dotyczą UDF-ów PySpark:
Ograniczenia dostępu do plików: W środowisku Databricks Runtime 14.2 i niżej funkcje zdefiniowane przez użytkownika PySpark w udostępnionych klastrach nie mogą uzyskiwać dostępu do folderów Git, plików obszarów roboczych ani woluminów Unity Catalog.
Zmienne rozgłaszane: Funkcje zdefiniowane przez użytkownika PySpark w klastrach w standardowym trybie dostępu i w obliczeniach bezserwerowych nie obsługują zmiennych rozgłaszanych.
- Limit pamięci bezserwerowej: funkcje zdefiniowane przez użytkownika PySpark w obliczeniach bezserwerowych mają limit pamięci 1 GB na funkcję zdefiniowanej przez użytkownika PySpark. Przekroczenie tego limitu powoduje błąd typu UDF_PYSPARK_USER_CODE_ERROR. MEMORY_LIMIT_SERVERLESS.
- Limit pamięci w standardowym trybie dostępu: UDF (funkcje zdefiniowane przez użytkownika) PySpark w standardowym trybie dostępu mają limit pamięci w zależności od dostępnej pamięci dla wybranego typu wystąpienia. Przekroczenie dostępnej pamięci powoduje błąd typu UDF_PYSPARK_USER_CODE_ERROR. MEMORY_LIMIT.
- Dostęp do sieci w bezserwerowych hurtowniach SQL: Domyślnie funkcje UDF języka Python w bezserwerowych hurtowniach SQL nie mogą wykonywać wychodzących żądań sieciowych, a zapytania, które próbują wykonywać wywołania sieciowe, zawieszają się na czas nieokreślony. Aby włączyć dostęp do sieci wychodzącej, włącz funkcję Publiczna wersja zapoznawcza Włącz sieć dla izolowanych obciążeń w bezserwerowych magazynach SQL Warehouse na stronie Podglądy obszaru roboczego. W przeciwnym razie użyj bezserwerowych lub klasycznych zasobów obliczeniowych w przypadku funkcji zdefiniowanych przez użytkownika, które wymagają dostępu do sieci.