ユーザー定義関数 (UDF) を使用すると、ClickHouse に標準で用意されている 1,000 種類を超える 関数 だけでは対応できない処理を追加できます。
ClickHouse Cloud では、ユーザー定義関数を作成および管理する方法がいくつかあります。
SQL ユーザー定義関数
SQL UDF は、ラムダ式を使って CREATE FUNCTION ステートメントで作成できます。
この例では、シンプルな実行可能ユーザー定義関数 isBusinessHours を作成します。
この関数は、特定のタイムスタンプが通常の営業時間内かどうかを確認し、該当すれば true、そうでなければ false を返します。
- Cloud Console にログインし、SQL コンソールを開きます
- 次の SQL クエリを入力して
isBusinessHours関数を作成します:
CREATE FUNCTION isBusinessHours AS (ts) ->
toDayOfWeek(ts) BETWEEN 1 AND 5
AND toHour(ts) BETWEEN 9 AND 17;- 新しく作成したUDFをテストするには、以下を実行します。
SELECT isBusinessHours('2026-03-20 10:00:00'::DateTime), isBusinessHours('2026-03-20 23:00:00'::DateTime);次の結果が返されるはずです:
1 0DROP FUNCTIONコマンドを使って、先ほど作成した UDF を削除できます。
DROP FUNCTION isBusinessHoursこれは、次のことを意味します。
- セッションレベルの設定 (
SETステートメントで設定したもの) は、UDF の実行コンテキストには引き継がれません - ユーザープロファイルの設定は UDFs に継承されません
- クエリレベルの設定は UDF の実行中には適用されません
UI で作成するユーザー定義関数
ClickHouse Cloud では、UI からユーザー定義関数を作成できます。
この例では、特定の timestamp が通常の営業時間内かどうかを判定する、前回と同じシンプルな実行可能ユーザー定義関数 isBusinessHours を作成します。
前回は SQL を使って作成しましたが、今回は Python で実装し、UI から設定します。
Python ファイルを作成する
ローカルで新しいファイル main.py を作成します。
cat > main.py << 'EOF'
import sys
from datetime import datetime
for line in sys.stdin:
ts = datetime.fromisoformat(line.strip())
result = 1 if (0 <= ts.weekday() <= 4 and 9 <= ts.hour <= 17) else 0
print(result)
sys.stdout.flush()
EOFPython スクリプトでサードパーティ製パッケージをインポートする場合は、それらを requirements.txt ファイルに記載すれば、ClickHouse Cloud がインストールしてくれます。代わりに依存関係を ZIP に直接含めることもできますが、その場合は両方の CPU アーキテクチャ向けにキャッシュ済みのパッケージを含める必要があるため、requirements.txt を使うほうが簡単です。たとえば、次のようになります。
requests>=2.28.0
numpy>=1.23.0依存関係パッケージとローカルファイルをまとめる
依存関係パッケージや追加のローカルファイル (wheel ファイル、設定ファイル、データファイルなど) を含めるには、main.py と requirements.txt と同じディレクトリに配置します。ZIP アーカイブを作成する際は、すべてのファイルを含めてください。
zip is_business_hours.zip main.py requirements.txtPython コードでは、os.path.dirname(os.path.abspath(__file__)) を使って、ローカルにバンドルされた path のベース directory を参照できます。これにより、ZIP アーカイブ内で main.py が配置されている directory の絶対 path が返され、バンドルされたほかのファイルにアクセスできるようになります。
import os
# Get the base directory of the bundled files
base_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(base_dir, 'config.json')これは、次のような場合に便利です:
- UDF に含まれている構成ファイルにアクセスする
- カスタム依存関係の wheel パッケージを読み込む
- 追加のスクリプトやデータファイルを参照する
次に、ファイルを ZIP アーカイブに圧縮します:
zip is_business_hours.zip main.pyUI で UDF を作成する
- Cloud コンソールのホームページで、左下のメニューにある組織名をクリックします。
- メニューから ユーザー定義関数 を選択します。
- ユーザー定義関数ページで UDF を設定 をクリックします。画面右側に設定パネルが開きます。
- 関数名を入力します。この例では
isBusinessHoursを使用します。 - 関数タイプとして Executable pool または Executable を選択します。
- Executable pool: 永続的なプロセスのプールが維持され、読み取り時にはそのプールからプロセスが割り当てられます。
- Executable: スクリプトはクエリごとに実行されます。
- この例では、デフォルト設定を使用します。設定パラメーターの一覧については、Executable user-defined functions を参照してください。
- ファイルを参照 をクリックして、このチュートリアルの冒頭で作成した
.zipファイルをアップロードします。 - 新しい引数を追加します。この例では、型
DateTimeの引数timestampを追加します。 - 戻り値の型を選択します。この例では
Boolを選択します。 - UDF を作成 をクリックします。現在のビルドステータスを示すダイアログが表示されます。
- 問題がある場合、ステータスは error に変わります。
- 問題がなければ、ステータスは building から provisioning に進みます。プロビジョニングを完了するには、サービスが稼働中である必要があります。サービスがアイドル状態の場合は、サービス名の横にある UDF details パネルで Wake Up Service をクリックします。
- 完了すると、ステータスは deployed に変わります。
UDFをテストする
- ページ左上の Settings - return to your service view をクリックして、SQL Console のホーム画面に戻ります
- 左側のメニューで SQL Console をクリックします
- 次のクエリを入力します:
SELECT isBusinessHours('2026-03-20 10:00:00'::DateTime), isBusinessHours('2026-03-20 23:00:00'::DateTime);以下の結果が表示されるはずです。
true false新しいバージョンを作成する
UDF のコードを変更するには、新しいバージョンを作成します。Edit パネルで管理できるのは、UDF をどのサービスに割り当てるかだけです。そこでファイルをアップロードしても、デプロイ済みのコードは置き換えられません。
- Cloud Console のホーム画面で、左下のメニューにある組織名をクリックします。
- メニューから User-defined functions を選択します。
isBusinessHoursUDF の Actions にある 3 点メニューを選択し、Create new version をクリックします- 変更したコードを含む zip をアップロードするか、設定を変更してから Create new version をクリックします
これで、UI から最初のユーザー定義関数を追加し、それが実行されることを確認し、必要に応じて新しいバージョンを作成する方法も確認できました。
Cloud API を使用して UDF を管理する
UI で利用できるすべての機能は、ClickHouse Cloud API を通じてプログラムからも利用できます。 UDF エンドポイントを使用すると、ソースアーカイブのアップロード、関数とバージョンの作成、サービスへのアタッチ、削除まで、UDF のライフサイクル全体をスクリプトで自動化できます。
API を介した UDF の作成とデプロイの一般的なワークフローは次のとおりです。
- 署名付き
application/zipアップロード URL を取得するためにアップロード URL を作成し、その URL に ZIP アーカイブをアップロードします。各アップロード ID は、作成またはバージョン作成の 1 回の試行にのみ使用できます。再試行する場合は、新しいアップロード URL をリクエストしてください。 - アップロードしたアーカイブから UDF を作成し、関数名、ランタイム、引数、戻り値の型を指定します。
- UDF をサービスにアタッチします。バージョンを省略した場合は、最新の準備完了バージョンがアタッチされます。サービスは実行中である必要があります。アイドル状態のサービスは事前に起動できます。
エンドポイントの一覧は次のとおりです。
| エンドポイント | 説明 |
|---|---|
| UDF アップロード URL を作成 | 組織スコープの署名付き application/zip アップロード URL を作成します |
| UDF を作成 | アップロードしたアーカイブから新しい UDF を作成します |
| UDF を一覧表示 | 組織内の各 UDF の最新バージョンを返します |
| UDF を取得 | UDF の最新バージョンを返します |
| UDF を削除 | UDF のすべてのバージョンを削除し、すべてのサービスからデタッチします |
| UDF バージョンを作成 | ソースアーカイブを使用してバージョンを割り当て、UDF のビルドを開始します |
| UDF バージョンを一覧表示 | UDF のすべてのバージョンを返します |
| UDF バージョンを削除 | どのサービスにもアタッチされていない UDF バージョンを削除します |
| UDF をサービスにアタッチ | 必要に応じて現在のバージョンを置き換え、UDF の 1 つのバージョンをサービスにアタッチします |
| UDF アタッチメントを一覧表示 | UDF の現在のサービスへのアタッチ状況を返します |
| UDF アタッチメントを取得 | 指定したサービスへの UDF の現在のアタッチ状況を返します |
| UDF をサービスからデタッチ | UDF をサービスからデタッチします |
リクエストおよびレスポンスのスキーマについては、UDF API リファレンスを参照してください。
Terraform で UDF を管理する
公式の ClickHouse Terraform プロバイダーには、Infrastructure as Code として UDF を管理するためのリソースが 2 つ含まれています。
clickhouse_udfは、関数自体を管理します。関数のソースコードを含む ZIP アーカイブを受け取り、アーカイブのハッシュが変更されるたびに新しいバージョンをパブリッシュし、ビルドの完了を待機します。clickhouse_udf_attachmentは、UDF のバージョンをサービスにアタッチします。サービスに関連付けられる関数のバージョンは、一度に最大 1 つです。固定のバージョン番号を指定することも、clickhouse_udf.<name>.versionを参照してサービスを最新バージョンに自動更新することもできます。
たとえば、前の例の isBusinessHours UDF を Terraform でデプロイするには、次のようにします。
resource "clickhouse_udf" "is_business_hours" {
function_name = "isBusinessHours"
runtime = "python3.11"
type = "executable_pool"
return_type = "Bool"
arguments = [
{ name = "timestamp", type = "DateTime" },
]
source_archive_path = "${path.module}/is_business_hours.zip"
source_archive_hash = filebase64sha256("${path.module}/is_business_hours.zip")
}
resource "clickhouse_udf_attachment" "production" {
function_name = clickhouse_udf.is_business_hours.function_name
service_id = var.service_id
version = clickhouse_udf.is_business_hours.version
}アタッチは準備完了のバージョンに対してのみ成功し、完了まで数分かかる場合があります。アイドル状態のサービスは自動的に起動します。clickhouse_udf リソースを削除すると、関数のすべてのバージョンが削除され、すべてのサービスからデタッチされます。