Skip to main content
ClickHouse は、いくつかの種類のユーザー定義関数 (UDFs) をサポートしています。
  • 実行可能 UDF は、外部プログラムやスクリプト (Python、Bash など) を起動し、STDIN / STDOUT を介してデータのブロックをストリーミングします。ClickHouse を再コンパイルすることなく、既存のコードやツールを統合するために使用できます。インプロセスの選択肢と比べると呼び出しごとのオーバーヘッドは大きく、より重いロジックや別のランタイムが必要な場合に適しています。
  • SQL UDFs は、CREATE FUNCTION を使って SQL のみで定義されます。これらはクエリプランにインライン展開されるため (プロセス境界はありません) 、軽量で、式ロジックの再利用や複雑な計算カラムの簡略化に適しています。
  • Experimental WebAssembly UDFs は、WebAssembly にコンパイルされたコードを、サーバープロセス内のサンドボックスで実行します。外部の実行可能ファイルよりも呼び出しごとのオーバーヘッドが低く、ネイティブ拡張機能よりも優れた分離性を備えているため、WASM をターゲットにできる言語 (例: C/C++/Rust) で記述されたカスタムアルゴリズムに適しています。
  • Experimental ドライバーベースの実行可能 UDF では、オペレーターが提供する “ドライバー” により、CREATE FUNCTION ... ENGINE = DriverName(...) AS '...' で指定されたコードスニペットを、関数作成時に実行可能 UDF に変換できます (たとえばコンパイルして)。これは実行可能 UDF をベースとしており、サーバー側のドライバー設定が必要です。

実行可能ユーザー定義関数

ClickHouse Cloud では、実行可能 UDF は一般提供 (GA) されており、Cloud コンソール、Cloud API、または Terraform から作成します。コンパイル済みバイナリ向けの Native ランタイムを含む Cloud 固有のワークフローについては、Cloud でのユーザー定義関数 を参照してください。
ClickHouse は、データ処理のために任意の外部実行可能プログラムまたはスクリプトを呼び出すことができます。 実行可能ユーザー定義関数の設定は、1 つ以上の XML ファイルに配置できます。 設定へのパスは、user_defined_executable_functions_config パラメータで指定します。 関数の設定には、次の項目が含まれます: コマンドは STDIN から引数を読み取り、結果を STDOUT に出力する必要があります。また、引数は反復的に処理する必要があります。つまり、1 つの chunk の引数を処理したら、次の chunk を待機しなければなりません。

実行可能ユーザー定義関数

例

インラインスクリプトからの UDF

XML または YAML の設定で execute_direct を 0 に明示的に指定し、test_function_sum を手動で作成します。
test_function.xml ファイル (デフォルトのパス設定では /etc/clickhouse-server/test_function.xml) 。
/etc/clickhouse-server/test_function.xml

Query
Result

Python スクリプトからの UDF

この例では、STDIN から値を読み取り、それを文字列として返す UDF を作成します。 XML または YAML の設定を使用して test_function を作成します。
ファイル test_function.xml (デフォルトのパス設定では /etc/clickhouse-server/test_function.xml) 。
/etc/clickhouse-server/test_function.xml

user_scripts フォルダー内にスクリプトファイル test_function.py を作成します (デフォルトのパス設定では /var/lib/clickhouse/user_scripts/test_function.py) 。
Query
Result

STDIN から 2 つの値を読み取り、その合計を JSON オブジェクトとして返す

名前付き引数と JSONEachRow フォーマットを使用して、XML または YAML の設定で test_function_sum_json を作成します。
ファイル test_function.xml (デフォルトのパス設定では /etc/clickhouse-server/test_function.xml) 。
/etc/clickhouse-server/test_function.xml

user_scripts フォルダー内にスクリプトファイル test_function_sum_json.py を作成します (デフォルトのパス設定では /var/lib/clickhouse/user_scripts/test_function_sum_json.py) 。
Query
Result

command 設定でパラメータを使用する

実行可能なユーザー定義関数では、command 設定で構成した定数パラメータを受け取れます (これは executable 型のユーザー定義関数でのみ機能します) 。 また、シェルの引数展開による脆弱性を防ぐため、execute_direct オプションも必要です。
ファイル test_function_parameter_python.xml (デフォルトのパス設定では /etc/clickhouse-server/test_function_parameter_python.xml) 。
/etc/clickhouse-server/test_function_parameter_python.xml

user_scripts フォルダ内にスクリプトファイル test_function_parameter_python.py を作成します (デフォルトのパス設定では /var/lib/clickhouse/user_scripts/test_function_parameter_python.py) 。
Query
Result

シェルスクリプトによるUDF

この例では、各値を 2 倍するシェルスクリプトを作成します。
ファイル test_function_shell.xml (デフォルトのパス設定の場合は /etc/clickhouse-server/test_function_shell.xml) 。
/etc/clickhouse-server/test_function_shell.xml

user_scripts フォルダー内に、スクリプトファイル test_shell.sh を作成します (デフォルトのパス設定の場合は /var/lib/clickhouse/user_scripts/test_shell.sh) 。
/var/lib/clickhouse/user_scripts/test_shell.sh
Query
Result

エラー処理

一部の関数では、データが無効な場合に例外がスローされることがあります。 この場合、クエリはキャンセルされ、エラーメッセージがクライアントに返されます。 分散処理では、いずれかのサーバーで例外が発生すると、他のサーバーでもクエリの中止が試みられます。

引数式の評価

ほとんどすべてのプログラミング言語では、特定の演算子では引数の1つが評価されないことがあります。 通常は、&&、||、?: といった演算子です。 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’ のすべての関数はこの分片のサーバーで実行されます。
通常、関数の結果は、どのサーバーで実行されるかに依存しません。ただし、これが重要になる場合もあります。 たとえば、Dictionary を扱う関数は、その関数が実行されているサーバー上にある Dictionary を使用します。 別の例として、hostName 関数は、自身が実行されているサーバーの名前を返します。これは、SELECT クエリでサーバーごとに GROUP BY できるようにするためです。 クエリ内の関数がリクエスト元のサーバーで実行されるものの、リモートサーバーで実行する必要がある場合は、その関数を ‘any’ 集約関数でラップするか、GROUP BY のキーに追加できます。

SQL ユーザー定義関数

ラムダ式からカスタム関数を作成するには、CREATE FUNCTION ステートメントを使用します。これらの関数を削除するには、DROP FUNCTION ステートメントを使用します。

WebAssembly ユーザー定義関数

WebAssembly ユーザー定義関数 (WASM UDFs) を使用すると、WebAssembly にコンパイルしたカスタムコードを ClickHouse サーバープロセス内で実行できます。

クイックスタート

ClickHouse の設定で、実験的な WebAssembly サポートを有効にします。
コンパイル済みのWASMモジュールをシステムテーブルに挿入します:
WASM モジュールを使って関数を作成します:
クエリではこの関数を使用します:

詳細情報

詳細については、WebAssembly ユーザー定義関数 のドキュメントを参照してください。

ドライバーベースの実行可能なユーザー定義関数

これは実験的な機能であり、将来のリリースで後方互換性のない変更が加えられる可能性があります。allow_experimental_executable_udf_drivers サーバー設定で有効にしてください。
ドライバー は、ユーザーのコードスニペットを実行可能な 実行可能 UDF に変換する、オペレーター提供のアダプターです。関数を ENGINE = DriverName(...) で作成すると、ClickHouse はドライバーの create_command を実行し、関数シグネチャとコードのボディを渡します。ドライバーはボディをコンパイルするか、別の方法で処理し、実行可能 UDF の設定を出力します。その後、ClickHouse はその設定を保存して読み込みます。 これにより管理者は、サーバーの設定ファイルやファイルシステムへのアクセスを与えることなく、任意の言語 (たとえば、サンドボックス化されたコンテナー内でコンパイルされる C) で関数を定義できる、安全かつ限定的な手段をユーザーに提供できます。利用可能なドライバーのセットは、オペレーターが完全に制御します。

ドライバーの有効化

ドライバーベースの実行可能 UDF は、デフォルトで無効になっています。有効にするには、次の手順を実行します。
  1. server configuration で Experimental のゲートを設定します。
  2. user_defined_executable_function_drivers_config に 1 つ以上の ドライバー設定 file を指定します (glob を使用可能) 。必要に応じて、生成された実行可能 UDF の configuration が保存されるディレクトリである dynamic_user_defined_executable_functions_path も設定します。
ドライバー registry は server の起動時に読み込まれ、SYSTEM RELOAD CONFIG で更新されるため、server を再起動せずにドライバーを追加、変更、削除できます。

ドライバー設定

ドライバーは、最上位要素として <driver> を持つ XML (または YAML) ファイルで記述します。サポートされるフィールドは次のとおりです。 ドライバー設定の例:

ドライバー呼び出し契約

CREATE FUNCTION を実行すると、設定された env 変数がセットされた状態で create_command が呼び出され、次の引数が渡されます。
  • --name <function_name>
  • --return <return_type> (RETURNS 句がある場合)
  • --args <signature> (ARGUMENTS 句がある場合) 。ここで、signature は宣言された引数の一覧で、たとえば x UInt8, y DateTime です
  • ENGINE = DriverName(key = value) で指定された、宣言済みの各 engine 引数について --<key> <value>
ユーザー code のボディ (AS の後のテキスト) は、コマンドの標準入力に送られます。コマンドは、実行可能 UDF の configuration を標準出力に出力する必要があります。フォーマットは自動検出され、< で始まる出力は XML、それ以外は YAML として扱われます。生成された configuration 内で定義される関数名は、作成する関数名と一致している必要があります。create_command がゼロ以外の status で終了した場合、ステートメントは終了コードとドライバーの標準エラーを含む例外とともに失敗します。 drop_command は、存在する場合、関数が削除されるときに同じ方法で呼び出されます (stdin に code のボディは渡されません) 。

function の作成

ClickHouse はドライバーの create_command を実行し、生成された設定を dynamic_user_defined_executable_functions_path に書き込みます。すると、既存の実行可能 UDF ローダーがそれを検出します。その後、その関数は他の関数と同様に呼び出せます。

関数の削除

DROP FUNCTION は、ドライバーの drop_command (存在する場合) を呼び出し、生成された動的設定と関数ごとの作業ディレクトリを削除し、実行可能 UDF ローダーを再読み込みして、永続化されたクエリを削除します。

永続化と再起動

元のクエリは、ユーザー定義 SQL オブジェクトディレクトリに ATTACH FUNCTION ... ステートメントとして永続化されるため、サーバーを再起動しても関数は保持されます。起動時には、dynamic_user_defined_executable_functions_path 内の生成済み構成が、ドライバーを再実行することなく直接読み込まれます。永続化された ATTACH FUNCTION に対応する生成済み構成がない場合 (たとえば動的ディレクトリが失われた場合) 、それを再作成するためにドライバーが再実行されます。

制限事項

  • この機能は実験的で、allow_experimental_executable_udf_drivers を有効にした場合にのみ利用できます。
  • ドライバーベースの関数は、レプリケーション対応のユーザー定義関数ストレージ (ON CLUSTER および <user_defined_zookeeper_path>) ではサポートされていません。レプリケートされるのは生成されたアーティファクトではなく、元のクエリだけであるためです。
  • バックアップされたドライバーベースの関数を RESTORE すると、クエリ自体は保持されますが、ドライバーは再実行されません。生成された設定は、その後の再起動時の復旧によって実体化されます。

例: C ドライバー

ソースツリーには、C の関数本体をコンパイルして実行する概念実証用ドライバーが programs/server/user_defined_executable_function_drivers_config.d/ 配下に含まれています。これらはあくまで例であり、パッケージには含まれず、インストールもされません。
  • DockerC - サンドボックス化された Docker コンテナー内でコードをコンパイルして実行し (--network=none --read-only --cap-drop=ALL --security-opt=no-new-privileges に加えて、メモリ/CPU/PID 制限も適用) 、executable_pool UDF を生成します。
  • GVisorC - コンパイル済みバイナリーを gVisor の runsc ランタイム上で実行するバリアントです。
  • UnsafeC - サンドボックスを使用せず、ホスト上でコードを直接コンパイルして実行します。名前のとおり分離は行われないため、信頼できる環境とテスト用途でのみ使用することを想定しています。
これらのサンプルドライバーは出発点として用意されています。信頼できないユーザーに公開する前に、利用環境に合わせてサンドボックス化の内容を確認し、強化してください。