DatabricksのUnity CatalogバッチPythonユーザー定義関数

こちらのアップデートです。

https://docs.databricks.com/gcp/en/release-notes/product/2025/april#batch-unity-catalog-python-udfs-public-preview

> **Unity CatalogバッチPython UDF(パブリックプレビュー)**
>
> Unity CatalogバッチPython UDFは、データのバッチを操作するPythonコードを書けるようにすることでUnity Catalog UDFの能力を拡張し、行ごとに処理するUDFに関連するオーバーヘッドを削減し、効率を劇的に改善します。バッチPython UDFは外部クラウドサービスにアクセスするためのサービス資格情報をサポートしています。[Unity CatalogのバッチPythonユーザー定義関数(UDF)](https://docs.databricks.com/aws/ja/udf/python-batch-udf)をご覧ください。

:::note info
リンク先のマニュアルの誤記は修正済みです。
:::

# Unity CatalogバッチPythonユーザー定義関数とは？

PySparkで使用できていた[Pandas UDF](https://docs.databricks.com/aws/ja/udf/pandas)をUnity Catalogで管理できるようになって、Unity CatalogバッチPythonユーザー定義関数として提供されました。これによって、大量データを高速に処理できるバッチ関数をガバナンスが適用された状況で共有できるようになります。

Pandas UDFに関してはこちらもご覧ください。

https://qiita.com/taka_yayoi/items/be78cb9988e2b3692451#pandas%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E5%AE%9A%E7%BE%A9%E9%96%A2%E6%95%B0

# 動かしてみる

Databricksランタイム16.3以降が必要です。

まずは、マニュアルにあるように一時関数として動かします。BMIを計算する関数です。

```sql
%sql
CREATE OR REPLACE TEMPORARY FUNCTION calculate_bmi_pandas(weight_kg DOUBLE, height_m DOUBLE)
RETURNS DOUBLE
LANGUAGE PYTHON
PARAMETER STYLE PANDAS
HANDLER 'handler_function'
AS $$
import pandas as pd
from typing import Iterator, Tuple

def handler_function(batch_iter: Iterator[Tuple[pd.Series, pd.Series]]) -> Iterator[pd.Series]:
  for weight_series, height_series in batch_iter:
    yield weight_series / (height_series ** 2)
$$;
```

呼び出します。

```sql
%sql
SELECT person_id, calculate_bmi_pandas(weight_kg, height_m) AS bmi
FROM (
  SELECT 1 AS person_id, CAST(70.0 AS DOUBLE) AS weight_kg, CAST(1.75 AS DOUBLE) AS height_m UNION ALL
  SELECT 2 AS person_id, CAST(80.0 AS DOUBLE) AS weight_kg, CAST(1.80 AS DOUBLE) AS height_m
);
```

|person_id|bmi|
|---|---|
|1|22.857142857142858|
|2|24.691358024691358|

次に、関数として永続化します。

```sql
%sql
CREATE OR REPLACE FUNCTION users.takaaki_yayoi.calculate_bmi_pandas(weight_kg DOUBLE, height_m DOUBLE)
RETURNS DOUBLE
LANGUAGE PYTHON
PARAMETER STYLE PANDAS
HANDLER 'handler_function'
AS $$
import pandas as pd
from typing import Iterator, Tuple

def handler_function(batch_iter: Iterator[Tuple[pd.Series, pd.Series]]) -> Iterator[pd.Series]:
  for weight_series, height_series in batch_iter:
    yield weight_series / (height_series ** 2)
$$;
```

登録されました。

![Screenshot 2025-04-16 at 9.36.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/0054ca8a-556e-4a74-8d9c-4780e278a1b4.png)

呼び出します。

```sql
%sql
SELECT person_id, users.takaaki_yayoi.calculate_bmi_pandas(weight_kg, height_m) AS bmi
FROM (
  SELECT 1 AS person_id, CAST(70.0 AS DOUBLE) AS weight_kg, CAST(1.75 AS DOUBLE) AS height_m UNION ALL
  SELECT 2 AS person_id, CAST(80.0 AS DOUBLE) AS weight_kg, CAST(1.80 AS DOUBLE) AS height_m
);
```

|person_id|bmi|
|---|---|
|1|22.857142857142858|
|2|24.691358024691358|

# まとめ

従来のPandas UDFと今回のUnity CatalogバッチPython UDFの機能自体は同等ですが、要件に応じて使い分けることが可能です。

Unity Catalogで作業をしており、Pandas UDF同等の機能が必要で、ガバナンスを集中管理したいのであれば、Unity CatalogバッチPython UDFが理想的なソリューションとなります。ガバナンスがそれほど重要でなく、純粋なデータ処理にフォーカスしたいのであれば、Pandas UDFで十分でしょう。

|  | Pandas UDF | Unity CatalogバッチPython UDF |
|:--|:--|:--|
| データのバッチ処理  | ⚪︎  | ⚪︎  |
| Unity Catalogでの管理  | ×  | ⚪︎  |

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)