使用英语阅读

通过


Unity Catalog 中 (UDF) 的用户定义函数

重要

此功能目前以公共预览版提供。

Unity 目录中的用户定义函数(UDF)扩展了 Azure Databricks 中的 SQL 和 Python 功能。 它们允许在计算环境中定义、使用和安全地共享和管理自定义函数。

在 Unity Catalog 中注册为函数的 Python UDF 在范围和支持方面不同于作用域为笔记本或 SparkSession 的 PySpark UDF。 请参阅用户定义标量函数 - Python

有关完整的 SQL 语言参考,请参阅 CREATE FUNCTION(SQL 和 Python)

要求

若要在 Unity 目录中使用 UDF,必须满足以下要求:

  • 若要在 Unity Catalog 中注册的 UDF 中使用 Python 代码,必须使用无服务器或 pro SQL 仓库或运行 Databricks Runtime 13.3 LTS 或更高版本的群集。
  • 如果视图包含 UC Python UDF,它将在 SQL 经典仓库上失败。

在 Unity 目录中创建 UDF

若要在 Unity 目录中创建 UDF,用户需要对目录的架构和 USAGE 权限具有 USAGE 和 CREATE 权限。 有关更多详细信息,请参阅 Unity 目录

若要运行 UDF,用户需要对 UDF 拥有 EXECUTE 权限。 用户还需要对架构和目录具有 USAGE 权限。

以下示例将新函数注册到 my_schema Unity 目录架构:

CREATE OR REPLACE FUNCTION my_catalog.my_schema.calculate_bmi(weight DOUBLE, height DOUBLE)
RETURNS DOUBLE
LANGUAGE SQL
AS
SELECT weight / (height * height);

适用于 Unity Catalog 的 Python UDF 使用双美元符号 ($$) 分隔语句。 还需要指定数据类型映射。 以下示例注册了计算正文质量索引的 UDF:

CREATE FUNCTION my_catalog.my_schema.calculate_bmi(weight_kg DOUBLE, height_m DOUBLE)
RETURNS DOUBLE
LANGUAGE PYTHON
AS $$
return weight_kg / (height_m ** 2)
$$;

现在可以在 SQL 查询或 PySpark 代码中使用此 Unity 目录函数:

SELECT person_id, my_catalog.my_schema.calculate_bmi(weight_kg, height_m) AS bmi
FROM person_data;

使用自定义依赖项扩展 UDF

重要

此功能目前以公共预览版提供。

可以通过为外部库定义自定义依赖项,将 Unity 目录 Python UDF 的功能扩展到 Databricks Runtime 环境之外。

可以从以下源安装依赖项:

  • PyPi 包
  • 存储在 Unity 目录卷中的文件 调用 UDF 的用户必须对源卷具有 READ VOLUME 权限。
  • 公共 URL 提供的文件 工作区的网络安全规则必须允许访问公共 URL。

备注

若要配置网络安全规则以允许从无服务器 SQL 仓库访问公共 URL,请参阅 使用 Databricks SQL 进行验证

以下计算类型支持 Unity 目录 UDF 的自定义依赖项:

  • 无服务器计算
  • 使用 Databricks Runtime 16.2 及更高版本的通用计算
  • SQL 仓库经典版或专业版

使用 UDF 定义的 ENVIRONMENT 节指定依赖项:

CREATE OR REPLACE FUNCTION my_catalog.my_schema.mixed_process(data STRING)
RETURNS STRING
LANGUAGE PYTHON
ENVIRONMENT (
  dependencies = '["simplejson==3.19.3", "/Volumes/my_catalog/my_schema/my_volume/packages/custom_package-1.0.0.whl", "https://my-bucket.s3.amazonaws.com/packages/special_package-2.0.0.whl?Expires=2043167927&Signature=abcd"]'
  environment_version = 'None'
)
AS $$
import simplejson as json
import custom_package
return json.dumps(custom_package.process(data))
$$;

ENVIRONMENT 部分包含以下字段:

字段 DESCRIPTION 类型 示例用法
dependencies STRING 要安装的逗号分隔依赖项的列表。 每个条目都是符合 pip 要求文件格式的字符串。 dependencies = '["simplejson==3.19.3", "/Volumes/catalog/schema/volume/packages/my_package-1.0.0.whl"]'
dependencies = '["https://my-bucket.s3.amazonaws.com/packages/my_package-2.0.0.whl?Expires=2043167927&Signature=abcd"]'
environment_version STRING 指定要在其中运行 UDF 的无服务器环境版本。
目前,仅支持该值 None
environment_version = 'None'

在 PySpark 中使用 Unity 目录 UDF

from pyspark.sql.functions import expr

result = df.withColumn("bmi", expr("my_catalog.my_schema.calculate_bmi(weight_kg, height_m)"))
display(result)

升级会话范围的 UDF

备注

Unity Catalog 中 Python UDF 的语法和语义不同于注册到 SparkSession 的 Python UDF。 请参阅 用户定义的标量函数 - Python

在 Azure Databricks 笔记本中给定以下基于会话的 UDF:

from pyspark.sql.functions import udf
from pyspark.sql.types import StringType

@udf(StringType())
def greet(name):
    return f"Hello, {name}!"

# Using the session-based UDF
result = df.withColumn("greeting", greet("name"))
result.show()

若要将此函数注册为 Unity 目录函数,请使用 SQL CREATE FUNCTION 语句,如以下示例所示:

CREATE OR REPLACE FUNCTION my_catalog.my_schema.greet(name STRING)
RETURNS STRING
LANGUAGE PYTHON
AS $$
return f"Hello, {name}!"
$$

在 Unity 目录中共享 UDF

UDF 的权限基于向注册 UDF 的目录、架构或数据库应用的访问控制进行管理。 有关详细信息,请参阅 Unity 目录

使用 Azure Databricks SQL 或 Azure Databricks 工作区 UI 向用户或组授予权限(建议)。

工作区 UI 中的权限

  1. 找到存储 UDF 的目录和架构,然后选择 UDF。
  2. 在 UDF 设置中查找 “权限” 选项。 添加用户或组并指定他们应具有的访问类型,例如 EXECUTE 或 MANAGE。

工作区 UI 中的 权限

使用 Azure Databricks SQL 的权限

以下示例向用户授予对函数的 EXECUTE 权限:

GRANT EXECUTE ON FUNCTION my_catalog.my_schema.calculate_bmi TO user@example.com;

若要删除权限,请使用 REVOKE 以下命令,如以下示例所示:

REVOKE EXECUTE ON FUNCTION my_catalog.my_schema.calculate_bmi FROM user@example.com;

UDF 最佳做法

对于需要可供所有用户访问的 UDF,Databricks 建议使用适当的访问控制创建专用目录和架构。

对于特定于团队的 UDF,请使用团队目录中的专用架构进行存储和管理。

Azure Databricks 建议在 UDF 的文档字符串中包含以下信息:

  • 当前版本号
  • 用于跟踪各个版本的修改的更改日志
  • UDF 的用途、参数和返回值
  • 如何使用 UDF 的示例

下面是一个符合最佳实践的 UDF 示例:

CREATE OR REPLACE FUNCTION my_catalog.my_schema.calculate_bmi(weight_kg DOUBLE, height_m DOUBLE)
RETURNS DOUBLE
COMMENT ”Calculates Body Mass Index (BMI) from weight and height.”
LANGUAGE PYTHON
AS $$
 """
Parameters:
calculate_bmi (version 1.2):
- weight_kg (float): Weight of the individual in kilograms.
- height_m (float): Height of the individual in meters.

Returns:
- float: The calculated BMI.

Example Usage:

SELECT calculate_bmi(weight, height) AS bmi FROM person_data;

Change Log:
- 1.0: Initial version.
- 1.1: Improved error handling for zero or negative height values.
- 1.2: Optimized calculation for performance.

 Note: BMI is calculated as weight in kilograms divided by the square of height in meters.
 """
if height_m <= 0:
 return None  # Avoid division by zero and ensure height is positive
return weight_kg / (height_m ** 2)
$$;

用于访问外部 API 的 UDF

可以使用 UDF 从 SQL 访问外部 API。 以下示例使用 Python requests 库发出 HTTP 请求。

备注

Python UDF 允许 TCP/UDP 网络流量通过端口 80、443 和 53 使用配置标准访问模式的无服务器计算或计算。

CREATE FUNCTION my_catalog.my_schema.get_food_calories(food_name STRING)
RETURNS DOUBLE
LANGUAGE PYTHON
AS $$
import requests

api_url = f"https://example-food-api.com/nutrition?food={food_name}"
response = requests.get(api_url)

if response.status_code == 200:
   data = response.json()
   # Assuming the API returns a JSON object with a 'calories' field
   calories = data.get('calories', 0)
   return calories
else:
   return None  # API request failed

$$;

用于安全性和合规性的 UDF

使用 Python UDF 实现自定义标记化、数据掩码、数据修订或加密机制。

以下示例在保持长度和域的同时屏蔽电子邮件地址的标识:

CREATE OR REPLACE FUNCTION my_catalog.my_schema.mask_email(email STRING)
RETURNS STRING
LANGUAGE PYTHON
AS $$
parts = email.split('@')
masked_username = username[0] + '*' * (len(username) - 2) + username[-1]
return f"{masked_username}@{domain}"
$$

以下示例在动态视图定义中应用此 UDF:

-- First, create the view
CREATE OR REPLACE VIEW my_catalog.my_schema.masked_customer_view AS
SELECT
  id,
  name,
  my_catalog.my_schema.mask_email(email) AS email
FROM my_catalog.my_schema.customer_data;

-- Now you can query the view
SELECT * FROM my_catalog.my_schema.masked_customer_view;
+---+------------+------------------------+------------------------+
| id|        name|                   email|           masked_email |
+---+------------+------------------------+------------------------+
|  1|    John Doe|   john.doe@example.com |  j*******e@example.com |
|  2| Alice Smith|alice.smith@company.com |a**********h@company.com|
|  3|   Bob Jones|    bob.jones@email.org |   b********s@email.org |
+---+------------+------------------------+------------------------+

限制

  • 可以在 Python UDF 中定义任意数量的 Python 函数,但所有函数都必须返回标量值。
  • Python 函数必须独立处理 NULL 值,并且所有类型映射都必须遵循 Azure Databricks SQL 语言映射。
  • 如果未指定目录或架构,则 Python UDF 将注册到当前活动架构。
  • Python UDF 在安全隔离的环境中执行,无权访问文件系统或内部服务。
  • 每个查询不能调用 5 个以上的 UDF。