ユーザー定義関数 (UDF)
実行可能なユーザー定義関数
この機能は、ClickHouse Cloudのプライベートプレビューでサポートされています。アクセスにはClickHouse Supportにご連絡ください。
ClickHouseは、データを処理するために外部の実行可能なプログラムまたはスクリプトを呼び出すことができます。
実行可能なユーザー定義関数の設定は、一つまたは複数のxmlファイルに保存されます。設定ファイルへのパスは user_defined_executable_functions_configパラメータで指定します。
関数の設定には以下の設定項目が含まれます:
name
- 関数名。command
- 実行するスクリプト名、またはexecute_direct
がfalseの場合のコマンド。argument
- 引数の説明(type
とオプションのname
)を含む引数。この引数はそれぞれ別の設定で説明されます。引数名がNativeやJSONEachRowのようなユーザー定義関数形式のシリアル化の一部である場合には、名前を指定する必要があります。デフォルトの引数名はc
+ argument_numberです。format
- コマンドに渡される引数のフォーマット。return_type
- 戻り値の型。return_name
- 戻り値の名前。戻り値の名前がNativeやJSONEachRowのようなユーザー定義関数形式のシリアル化の一部である場合には、戻り値名を指定する必要があります。オプション。デフォルト値はresult
です。type
- 実行可能なタイプ。type
がexecutable
に設定されている場合、単一のコマンドが開始されます。executable_pool
に設定されている場合は、コマンドのプールが作成されます。max_command_execution_time
- データブロックを処理するための最大実行時間(秒単位)。この設定はexecutable_pool
コマンドにのみ有効です。オプション。デフォルト値は10
です。command_termination_timeout
- コマンドがそのパイプが閉じられたあとに完了するべき時間(秒単位)。その時間が過ぎると、SIGTERM
が実行中のコマンドに送信されます。オプション。デフォルト値は10
です。command_read_timeout
- コマンドのstdoutからデータを読み取るためのタイムアウト(ミリ秒単位)。デフォルト値は10000。オプションのパラメータです。command_write_timeout
- コマンドのstdinにデータを書くためのタイムアウト(ミリ秒単位)。デフォルト値は10000。オプションのパラメータです。pool_size
- コマンドプールのサイズ。オプション。デフォルト値は16
です。send_chunk_header
- チャンクのデータを処理する前に行数を送信するかどうかを制御します。オプション。デフォルト値はfalse
です。execute_direct
-execute_direct
=1
の場合、command
は user_scripts_pathで指定されたuser_scriptsフォルダ内で検索されます。追加のスクリプト引数は、空白で区切って指定できます。例:script_name arg1 arg2
。execute_direct
=0
の場合、command
はbin/sh -c
の引数として渡されます。デフォルト値は1
です。オプションのパラメータです。lifetime
- 関数の再読み込み間隔(秒単位)。0
に設定されている場合、関数は再読み込みされません。デフォルト値は0
です。オプションのパラメータです。
コマンドは引数をSTDIN
から読み取り、結果をSTDOUT
に出力しなければなりません。コマンドは引数を反復的に処理する必要があります。すなわち、引数のチャンクを処理した後は、次のチャンクを待たなければなりません。
例
インラインスクリプト
execute_direct
を0
に指定してtest_function_sum
を手動で作成します。
ファイルtest_function.xml
(/etc/clickhouse-server/test_function.xml
のデフォルトパス設定)。
クエリ:
結果:
Pythonスクリプト
STDIN
から値を読み取り、それを文字列として返します:
XML設定を使用してtest_function
を作成します。
ファイルtest_function.xml
(/etc/clickhouse-server/test_function.xml
のデフォルトパス設定)。
user_scripts
フォルダ内のスクリプトファイルtest_function.py
(/var/lib/clickhouse/user_scripts/test_function.py
のデフォルトパス設定)。
クエリ:
結果:
STDIN
から2つの値を読み取り、JSONオブジェクトとしてその合計を返します:
XML設定を使用して名前付き引数とフォーマットJSONEachRowのtest_function_sum_json
を作成します。
ファイル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
のデフォルトパス設定)。
クエリ:
結果:
command
設定のパラメータを使用:
実行可能なユーザー定義関数は、command
設定で構成された定数パラメータを取ることができます(これはexecutable
タイプのユーザー定義関数に対してのみ機能します)。また、execute_direct
オプションも必要です(シェル引数の展開脆弱性を回避するため)。
ファイル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
のデフォルトパス設定)。
クエリ:
結果:
シェルスクリプト
各値を2倍にするシェルスクリプト:
実行可能なユーザー定義関数はシェルスクリプトでも使用できます。
ファイルtest_function_shell.xml
(/etc/clickhouse-server/test_function_shell.xml
のデフォルトパス設定)。
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ステートメントを使用します。