UDFs User Defined Functions
ClickHouse は複数の種類のユーザー定義関数 (UDFs) をサポートしています:
- Executable UDFs は外部プログラムやスクリプト (Python、Bash など) を起動し、STDIN / STDOUT を介してデータブロックをストリーミングします。ClickHouse を再コンパイルせずに既存のコードやツールを統合するために利用します。プロセス内で実行される方式と比べて呼び出しごとのオーバーヘッドは大きくなりますが、より重いロジックや、異なるランタイムが必要な場合に最適です。
- SQL UDFs は
CREATE FUNCTIONにより、純粋に SQL だけで定義されます。クエリプランにインライン展開され (プロセス境界はありません)、軽量であるため、式のロジックの再利用や複雑な計算カラムの単純化に最適です。 - Experimental WebAssembly UDFs は WebAssembly にコンパイルされたコードを、サーバープロセス内のサンドボックスで実行します。外部実行ファイルよりも呼び出しごとのオーバーヘッドが小さく、ネイティブ拡張よりも高い分離性を提供するため、WASM をターゲットにできる言語 (例: C/C++/Rust) で書かれたカスタムアルゴリズムに適しています。
実行可能ユーザー定義関数
この機能は ClickHouse Cloud でプライベートプレビューとしてサポートされています。 利用を希望する場合は https://clickhouse.cloud/support から ClickHouse Support にお問い合わせください。
ClickHouse は、任意の外部実行可能プログラムやスクリプトを呼び出してデータを処理できます。
実行可能ユーザー定義関数の設定は、1つ以上の XML ファイルに配置できます。
設定ファイルへのパスは、パラメータ user_defined_executable_functions_config で指定します。
関数の設定には、次の項目が含まれます。
| Parameter | Description | Required | Default Value |
|---|---|---|---|
name | 関数名 | Yes | - |
command | 実行するスクリプト名、または execute_direct が false の場合はコマンド | Yes | - |
argument | 引数の type と、任意の name を含む引数の説明。各引数は個別の設定で記述します。Native や JSONEachRow など、ユーザー定義関数のフォーマットで引数名がシリアライズの一部となる場合は、name の指定が必要です | Yes | c + argument_number |
format | 引数をコマンドに受け渡す際に使用する format。コマンドの出力も同じフォーマットであることが想定されています | Yes | - |
return_type | 戻り値の型 | Yes | - |
return_name | 戻り値の名前。Native や JSONEachRow など、ユーザー定義関数のフォーマットで戻り値の名前がシリアライズの一部となる場合は、戻り値の名前の指定が必要です | Optional | result |
type | 実行タイプ。type が executable に設定されている場合は単一のコマンドが起動されます。executable_pool に設定されている場合はコマンドのプールが作成されます | Yes | - |
max_command_execution_time | データブロックを処理するための最大実行時間(秒)。この設定は executable_pool コマンドにのみ有効です | Optional | 10 |
command_termination_timeout | パイプがクローズされた後、コマンドが終了すべき時間(秒)。この時間を過ぎると、コマンドを実行しているプロセスに SIGTERM が送信されます | Optional | 10 |
command_read_timeout | コマンドの stdout からデータを読み取る際のタイムアウト(ミリ秒) | Optional | 10000 |
command_write_timeout | コマンドの stdin にデータを書き込む際のタイムアウト(ミリ秒) | Optional | 10000 |
pool_size | コマンドプールのサイズ | Optional | 16 |
send_chunk_header | データのチャンクを処理に送る前に行数を送信するかどうかを制御します | Optional | false |
execute_direct | execute_direct = 1 の場合、command は user_scripts_path で指定された user_scripts フォルダ内から検索されます。追加のスクリプト引数は空白区切りで指定できます(例: script_name arg1 arg2)。execute_direct = 0 の場合、command は bin/sh -c への引数として渡されます | Optional | 1 |
lifetime | 関数をリロードする間隔(秒)。0 に設定された場合、関数はリロードされません | Optional | 0 |
deterministic | 関数が決定的(同じ入力に対して常に同じ結果を返す)かどうか | Optional | false |
コマンドは STDIN から引数を読み込み、結果を STDOUT に出力しなければなりません。コマンドは引数を逐次的に処理する必要があります。つまり、あるチャンクの引数を処理した後、次のチャンクを待機しなければなりません。
実行可能なユーザー定義関数
例
インラインスクリプトを用いた UDF
XML または YAML 設定を使用して、execute_direct を 0 に設定した test_function_sum を手動で作成します。
- XML
- YAML
ファイル test_function.xml(デフォルトのパス設定の場合は /etc/clickhouse-server/test_function.xml)。
ファイル test_function.yaml(デフォルトのパス設定の場合は /etc/clickhouse-server/test_function.yaml)。
Python スクリプトからの UDF
この例では、STDIN から値を読み取り、それを文字列として返す UDF を作成します。
XML または YAML のいずれかの設定で test_function を作成します。
- XML
- YAML
ファイル test_function.xml(デフォルトのパス設定の場合は /etc/clickhouse-server/test_function.xml)。
ファイル test_function.yaml(デフォルトのパス設定の場合は /etc/clickhouse-server/test_function.yaml)。
user_scripts ディレクトリ内にスクリプトファイル test_function.py を作成します(デフォルトのパス設定では /var/lib/clickhouse/user_scripts/test_function.py)。
STDIN から 2 つの値を読み取り、それらの合計を JSON オブジェクトとして返す
名前付き引数と JSONEachRow フォーマットを使用して、XML または YAML の設定で test_function_sum_json を作成します。
- XML
- YAML
ファイル test_function.xml(パス設定がデフォルトの場合は /etc/clickhouse-server/test_function.xml)。
ファイル test_function.yaml(パス設定がデフォルトの場合は /etc/clickhouse-server/test_function.yaml)。
user_scripts フォルダ内にスクリプトファイル test_function_sum_json.py を作成します(パス設定がデフォルトの場合は /var/lib/clickhouse/user_scripts/test_function_sum_json.py)。
command 設定でパラメータを使用する
実行可能なユーザー定義関数は、command 設定で指定された定数パラメータを受け取ることができます(これは executable 型のユーザー定義関数でのみ動作します)。
また、シェルによる引数展開に起因する脆弱性を防ぐために、execute_direct オプションが必要です。
- XML
- YAML
File test_function_parameter_python.xml(デフォルトのパス設定では /etc/clickhouse-server/test_function_parameter_python.xml)。
File test_function_parameter_python.yaml(デフォルトのパス設定では /etc/clickhouse-server/test_function_parameter_python.yaml)。
user_scripts フォルダ内にスクリプトファイル test_function_parameter_python.py を作成します(デフォルトのパス設定では /var/lib/clickhouse/user_scripts/test_function_parameter_python.py)。
シェルスクリプトを使った UDF
この例では、各値を 2 倍にするシェルスクリプトを作成します。
- XML
- YAML
ファイル test_function_shell.xml(デフォルトのパス設定の場合は /etc/clickhouse-server/test_function_shell.xml)。
ファイル test_function_shell.yaml(デフォルトのパス設定の場合は /etc/clickhouse-server/test_function_shell.yaml)。
user_scripts ディレクトリ内にスクリプトファイル test_shell.sh を作成します(デフォルトのパス設定の場合は /var/lib/clickhouse/user_scripts/test_shell.sh)。
エラー処理
一部の関数は、データが無効な場合に例外をスローすることがあります。 この場合、クエリは中断され、エラーメッセージがクライアントに返されます。 分散処理では、いずれかのサーバーで例外が発生すると、他のサーバーもクエリの中断を試みます。
引数式の評価
ほとんどのプログラミング言語では、特定の演算子において、引数の一方が評価されないことがあります。
通常、これは演算子 &&、||、および ?: に当てはまります。
ClickHouse では、関数(演算子)の引数は常に評価されます。
これは、行ごとに個別に計算するのではなく、列の一部をまとめて一度に評価するためです。
分散クエリ処理における関数の実行
分散クエリ処理では、クエリ処理のできるだけ多くの段階をリモートサーバー上で実行し、残りの段階(中間結果のマージとそれ以降のすべて)はリクエスト元サーバーで実行します。
つまり、関数は異なるサーバー上で実行される場合があります。
例えば、次のクエリ SELECT f(sum(g(x))) FROM distributed_table GROUP BY h(y), では、
distributed_tableに少なくとも 2 つのシャードがある場合、関数gとhはリモートサーバー上で実行され、関数fはリクエスト元サーバー上で実行されます。distributed_tableに 1 つのシャードしかない場合、関数f、g、hはすべてこのシャードのサーバー上で実行されます。
関数の結果は通常、それがどのサーバーで実行されるかには依存しません。しかし、これが重要になる場合もあります。
例えば、辞書を扱う関数は、自身が実行されているサーバー上に存在する辞書を使用します。
別の例として hostName 関数は、SELECT クエリでサーバー単位の GROUP BY を行えるように、自身が実行されているサーバー名を返します。
クエリ内の関数がリクエスト元サーバーで実行されるようになっていても、それをリモートサーバー上で実行する必要がある場合は、その関数を any 集約関数でラップするか、GROUP BY 句のキーに追加することができます。
SQL ユーザー定義関数
ラムダ式を用いてカスタム関数を作成するには、CREATE FUNCTION ステートメントを使用します。これらの関数を削除するには、DROP FUNCTION ステートメントを使用します。
WebAssembly ユーザー定義関数
WebAssembly ユーザー定義関数 (WASM UDF) を使用すると、WebAssembly にコンパイルされた独自コードを ClickHouse サーバープロセス内で実行できます。
クイックスタート
ClickHouse の設定で実験的な WebAssembly サポートを有効にします。
コンパイル済みの WASM モジュールを system テーブルに挿入します。
WASM モジュールを使用して関数を作成します:
クエリでこの関数を使用します:
詳細情報
詳しくは、WebAssembly ユーザー定義関数 のドキュメントを参照してください。