📣新登場!TiDB Cloud BYOC、TiDB Cloud Filesystem、PostgreSQL-compatible TiDB Cloud Starter がパブリックプレビュー中。このページは自動翻訳されたものです。原文はこちらからご覧ください。

ユーザー定義関数タイプを選択する



ユーザー定義関数(UDF)を使用すると、組み込み SQL 関数では提供されていない再利用可能なロジックをパッケージ化できます。これにより、ビジネスルールの標準化、複雑なクエリの簡素化、カスタム集計の実装、値の行への展開、または SQL クエリと独立してホストされる Python サービスとの接続が可能になります。

UDF を作成する前に、SQL 関数リファレンスを確認してください。通常、組み込み関数は最もシンプルな実装、最も低い実行オーバーヘッド、そして最も小さい運用負荷を提供します。

UDF を使用する理由

分析ワークロードが増えるにつれて、同じ変換処理が多くのクエリで繰り返し現れることがよくあります。すべてのクエリに式をコピーすると、動作の一貫性を保つことや、安全に変更を展開することが難しくなります。

UDF は、次のようなタスクに役立ちます。

  • データクレンジング、検証、ビジネス計算を標準化する。
  • パラメーター化された SQL クエリをカプセル化する。
  • 中間状態を必要とするカスタム集計を実装する。
  • Python ライブラリ、独自ロジック、または機械学習モデルを呼び出す。
  • Warehouse とは独立して特化したコンピュートをスケールさせる。

UDF は 1 つの明確な責務だけを持つべきです。データ移動、スケジューリング、ストリーミング状態、継続的なイベントストリーム間の結合、ワークフローオーケストレーションは、UDF の内部ではなく、対応する Lake SQL、Stream、Task、または統合機能に属します。

UDF エコシステムを理解する

TiDB Cloud Lake は複数の UDF 実行モデルを提供します。これらは、戻り値の形状、言語、ホスティング、運用責任の点で異なります。

UDF タイプ実装出力ホスティング典型的な用途
SQL スカラー UDFSQL 式各入力行に対して 1 つの値TiDB Cloud Lake により管理書式設定、計算、再利用可能な条件
スクリプトスカラー UDFPython または JavaScript各入力行に対して 1 つの値TiDB Cloud Lake により管理ビジネスルール、検証、構造化データ処理
WebAssembly スカラー UDFWebAssembly モジュール各入力行に対して 1 つの値TiDB Cloud Lake により管理WebAssembly にコンパイルされた計算集約型ロジック
集計 UDFPython または JavaScript各グループに対して 1 つの値TiDB Cloud Lake により管理カスタムの状態を持つ集計
SQL テーブル UDFSQL クエリ結果セットTiDB Cloud Lake により管理再利用可能なパラメーター化クエリ
外部スカラー UDFPython UDF Server各入力行に対して 1 つの値ユーザーがホストライブラリ、モデル、独自サービス
外部テーブル UDFPython UDF Server複数のカラムまたは行ユーザーがホストトークン化、展開、レコード生成

集計 UDF とテーブル UDF は異なる問題を解決します。集計 UDF は複数行を消費して 1 つの値を返します。テーブル UDF は結果セットを返します。TiDB Cloud Lake は、これら 2 つの実行モデルを組み合わせた Python のテーブル集計 UDF を提供していません。

最もシンプルな実行モデルを選択する

実装を選択する際は、次の順序を使用してください。

  1. 必要な動作をすでに提供している場合は、組み込み関数を使用します。
  2. SQL でロジックを明確に表現できる場合は、SQL スカラー UDF またはテーブル UDF を使用します。
  3. TiDB Cloud Lake 内で実行すべきスクリプトロジックには、埋め込み型の Python または JavaScript スカラー UDF を使用します。
  4. コンパイル済みモジュールとして提供される計算集約型のスカラーロジックには、WebAssembly を使用します。
  5. 計算にカスタム集計状態が必要な場合は、集計 UDF を使用します。
  6. ロジックがリモートサービス、GPU、または独立したスケーリングに依存する場合は、外部 UDF を使用します。

次の質問は、選択肢を絞り込むのに役立ちます。

質問推奨オプション
1 つの SQL 式で結果を生成できますか。SQL スカラー UDF
行レベルのロジックに Python または JavaScript が必要ですか。スクリプトスカラー UDF
計算集約型の行レベルロジックに、コンパイル済みでポータブルなモジュールが必要ですか。WebAssembly スカラー UDF
SQL クエリが複数行を返す必要がありますか。SQL テーブル UDF
複数の入力行を 1 つのカスタム結果にまとめる必要がありますか。集計 UDF
1 つの入力から Python によって生成された複数行を生成する必要がありますか。外部テーブル UDF
ロジックに Python パッケージ、モデル、ネットワーク呼び出し、または別個のコンピュートが必要ですか。外部スカラーまたはテーブル UDF

再利用可能な変換には SQL スカラー UDF を使用する

SQL スカラー UDF は、各入力行を 1 つの値にマッピングします。これは、計算、文字列の正規化、条件付きビジネスルールに適しています。

電話番号を正規化する

次の関数は書式文字を削除し、後続のクエリで 1 つの電話番号表現を使用できるようにします。

CREATE FUNCTION normalize_phone(phone VARCHAR) RETURNS VARCHAR AS $$ REGEXP_REPLACE(phone, '[^0-9]', '') $$; SELECT normalize_phone('+1 (415) 555-0100');

割引を適用する

次の関数は割引計算を一元化します。

CREATE FUNCTION apply_discount( price DECIMAL(10, 2), rate DECIMAL(5, 2) ) RETURNS DECIMAL(10, 2) AS $$ price * (1 - rate) $$; SELECT apply_discount(100, 0.15);

共有ビジネスルールが変更された場合は、ALTER FUNCTIONを使用します。そうすることで、その関数を呼び出すクエリは式を重複させることなく新しい定義を使用できます。

完全な構文については、CREATE SCALAR FUNCTIONを参照してください。

データ処理ロジックには Python スカラー UDF を使用する

Python スカラー UDF は、ロジックに制御フロー、Python 標準ライブラリ、または SQL で表現しにくいパッケージが必要な場合に役立ちます。

次の関数は、住所内の空白と大文字小文字を標準化します。

CREATE FUNCTION normalize_address(value VARCHAR) RETURNS VARCHAR LANGUAGE python HANDLER = 'normalize_address' AS $$ def normalize_address(value): return " ".join(value.strip().upper().split()) $$; SELECT normalize_address(' 123 Main Street ');

Python UDF は、PyPI 依存関係に PACKAGES を、stage に保存されたファイルに IMPORTS を使用することもできます。依存関係は必要最小限に絞ることで、関数環境の再現と管理が容易になります。

JSON 変換には JavaScript スカラー UDF を使用する

JavaScript は、オブジェクトや JSON の変換に自然に適しており、特にそのロジックがすでにアプリケーションコードベースに存在する場合に有効です。

次の関数は、メールアドレスを正規化し、機密フィールドを削除します。

CREATE FUNCTION clean_profile(value VARIANT) RETURNS VARIANT LANGUAGE javascript HANDLER = 'cleanProfile' AS $$ export function cleanProfile(value) { const result = { ...value }; if (typeof result.email === 'string') { result.email = result.email.trim().toLowerCase(); } delete result.ssn; return result; } $$;

入力スキーマと戻り値スキーマは安定させてください。オブジェクト形状の変更は、その関数を呼び出すすべてのクエリに影響する可能性があります。

コンパイル済みロジックには WebAssembly UDF を使用する

WebAssembly UDF は、コンパイル済みコードをポータブルなモジュールとしてパッケージ化します。これは、スクリプトランタイムよりもコンパイル済み実装が望ましい計算集約型のスカラーロジックに適しています。

必要な Arrow UDF インターフェースを実装したモジュールを stage にアップロードし、その後ハンドラーを登録します。

CREATE FUNCTION fib_wasm(value INT) RETURNS INT LANGUAGE wasm HANDLER = 'fib' AS $$ @my_wasm_stage/arrow_udf_example.wasm $$; SELECT fib_wasm(10);

モジュールは、指定されたハンドラーをエクスポートし、SQL 互換の入力型と出力型を使用する必要があります。他のユーザーに関数を公開する前に、代表的な値でコンパイル済みアーティファクトをテストしてください。

カスタムな状態を持つ計算に集計 UDF を使用する

集計 UDF は、次の方法を定義します。

  1. 初期の集計状態を作成する。
  2. 各入力行を状態に追加する。
  3. 分散実行で生成された部分状態をマージする。
  4. 最終状態を 1 つの結果に変換する。

次の Python 集計は値を加算します。この特定の計算では組み込みの SUM を使うほうが適していますが、この例はカスタム集計に必要なライフサイクルを示しています。

CREATE FUNCTION py_total(value BIGINT) STATE { total BIGINT } RETURNS BIGINT LANGUAGE python AS $$ class State: def __init__(self): self.total = 0 def create_state(): return State() def accumulate(state, value): state.total += value return state def merge(left, right): left.total += right.total return left def finish(state): return state.total $$; SELECT py_total(number) FROM numbers(5);

集計 UDF は Python と JavaScript をサポートしています。必要な状態遷移や最終化ロジックを組み込みの集計関数で表現できない場合にのみ使用してください。その他の例については、CREATE AGGREGATE FUNCTION を参照してください。

再利用可能な結果セットに SQL テーブル UDF を使用する

SQL テーブル UDF は SQL クエリをカプセル化し、行とカラムを返します。再利用可能なフィルター、小規模なレポート用データセット、パラメーター化された変換に役立ちます。

CREATE FUNCTION small_numbers(max_value INT) RETURNS TABLE(value UINT64, doubled UINT64) AS $$ SELECT number AS value, number * 2 AS doubled FROM numbers(10) WHERE number < max_value $$; SELECT * FROM small_numbers(3);

関数本体は SQL クエリです。LANGUAGE python は受け付けません。Python で生成した行を使用する場合は、外部テーブル UDF を使用してください。

完全な構文については、CREATE TABLE FUNCTION を参照してください。

特殊なロジックに外部 Python UDF を使用する

tidbcloudlake-udf パッケージは、外部スカラー UDF およびテーブル UDF 用の Python UDF Server を提供します。Python プロセスはお使いのインフラストラクチャ上で実行されるため、カスタムパッケージ、独自コード、GPU コンピュート、および独立したスケーリングを利用できます。

Python で住所を正規化する

SDK をインストールします。

python3 -m pip install tidbcloudlake-udf

ハンドラーを定義してサーバーを起動します。

from tidbcloudlake_udf import UDFServer, udf @udf( input_types=["VARCHAR"], result_type="VARCHAR", skip_null=True, ) def normalize_address(value: str) -> str: return " ".join(value.strip().upper().split()) if __name__ == "__main__": server = UDFServer("0.0.0.0:8815") server.add_function(normalize_address) server.serve()

サーバーをデプロイして許可リストに追加した後、ハンドラーを登録します。

CREATE FUNCTION normalize_address(value VARCHAR) RETURNS VARCHAR LANGUAGE python HANDLER = 'normalize_address' ADDRESS = 'https://udf.example.com';

テキストを行に展開する

外部テーブル UDF は、result_type に出力カラムのリストを使用します。

@udf( input_types=["VARCHAR"], result_type=[("token", "VARCHAR")], skip_null=True, ) def split_words(value: str): return [{"token": token} for token in value.split()]

テーブルハンドラーを登録して呼び出します。

CREATE FUNCTION split_words(value VARCHAR) RETURNS TABLE(token VARCHAR) LANGUAGE python HANDLER = 'split_words' ADDRESS = 'https://udf.example.com'; SELECT * FROM split_words('external UDF server');

完全なサーバー、デプロイ、並行性、登録のワークフローについては、CREATE FUNCTION を参照してください。

外部 UDF を安全にデプロイする

外部関数を登録する前に、次を実施してください。

  • UDF Server を公開 HTTPS エンドポイントにデプロイする。
  • エンドポイントのホスト名をテナントの UDF サーバー許可リストに追加するため、TiDB Cloud Support に連絡する。
  • ゲートウェイで認証、キャパシティ、タイムアウト、高可用性、アップグレード、監視を設定する。
  • 認証情報は SQL 関数定義ではなく、サーバーのデプロイ環境に保持する。

SQL の ADDRESS には公開エンドポイントを含める必要があります。サーバープロセスはデプロイ環境内で 0.0.0.0 を listen できますが、Cloud クエリサービスが呼び出すアドレスとして localhost と 0.0.0.0 は無効です。

外部 UDF はネットワークレイテンシーを追加します。レイテンシーに敏感な行ごとの呼び出しは小さく保ち、可能な場合は作業をバッチ化し、1 つのクエリ内で同じ高コストな関数を繰り返し呼び出すことは避けてください。

パフォーマンスと運用を比較する

パフォーマンスは、関数の複雑さ、入力サイズ、パッケージ起動、Warehouse リソース、ネットワークレイテンシー、バッチサイズ、UDF Server のキャパシティに依存します。別の製品やデプロイで測定した結果から Lake のパフォーマンスを予測できません。

UDF の種類主なオーバーヘッド運用責任
SQL スカラー UDFSQL 式の評価TiDB Cloud Lake により管理
Python または JavaScript スカラー UDFスクリプトランタイムと依存関係の初期化TiDB Cloud Lake により管理
WebAssembly スカラー UDFモジュールのロードとコンパイル済み関数の実行TiDB Cloud Lake により管理
集計 UDFスクリプトランタイムと状態のシリアル化TiDB Cloud Lake により管理
SQL テーブル UDFクエリ実行TiDB Cloud Lake により管理
外部 UDFネットワーク転送と外部コンピュートTiDB Cloud Lake とお使いの UDF Server デプロイで分担

実際の関数を、代表的なデータと並行性でベンチマークしてください。クエリレイテンシー、スループット、エラーハンドリング、コールドスタート、外部サービスの飽和を測定してください。

UDF のベストプラクティスに従う

  • スクリプトやサービスを導入する前に、まず組み込み関数と SQL を優先する。
  • 可能な限り、各関数は決定的で単一目的に保つ。
  • NULL の動作を明示的に定義し、NULL 許容入力をテストする。
  • 不要な変換を避けるため、正確な入力型と戻り値型を使用する。
  • 集計 UDF では、部分状態を安全に結合できるように merge が結合則を満たすようにする。
  • 外部 UDF では、バッチ指向ライブラリには batch_mode を、I/O バウンドな行処理には io_threads を使用する。
  • 外部依存関係の過負荷を防ぐために max_concurrency を設定する。
  • 外部ハンドラーの変更はサービス API の変更として扱い、登録済み SQL 定義との互換性を保ってデプロイする。
  • ユーザーホスト型サーバーについて、エラー、レイテンシー、飽和、依存関係の健全性を監視する。
  • 未使用の UDF 登録とサーバーハンドラーは一緒に削除する。

はじめに

必要な出力に応じて、次のステップを選択してください。

このページは役に立ちましたか?