ClickHouseでのストアドプロシージャの代替手段
ClickHouse は、制御フローロジック (IF/ELSE、ループなど) を含む従来型のストアドプロシージャをサポートしていません。
これは、分析データベースとしての ClickHouse のアーキテクチャに基づく意図的な設計です。
分析データベースでは、単純なクエリを O(n) 回処理するよりも、より複雑なクエリを少ない回数で処理するほうが通常は高速なため、ループは推奨されません。
ClickHouse は、次のような用途に最適化されています。
- 分析ワークロード - 大規模なデータセットに対する複雑な集計
- バッチ処理 - 大量のデータを効率的に処理すること
- 宣言的クエリ - データをどのように処理するかではなく、どのデータを取得するかを記述する SQL クエリ
ユーザー定義関数 (UDFs)
ユーザー定義関数 (UDFs) を使うと、制御フローを伴わない再利用可能なロジックをまとめて定義できます。ClickHouse は次の 2 種類をサポートしています。ラムダベースのUDF
SQL 式とラムダ構文を使用して関数を作成します。例で使用するサンプルデータ
例で使用するサンプルデータ
- ループや複雑な制御フローは使用できません
- データは変更できません (
INSERT/UPDATE/DELETE) - 再帰関数は使用できません
CREATE FUNCTION を参照してください。
実行可能 UDF
より複雑なロジックには、外部プログラムを呼び出す実行可能 UDF を使用できます。パラメーター化ビュー
パラメーター化ビューは、データセットを返す関数のように動作します。 動的なフィルタリングを伴う再利用可能なクエリに最適です。例で使用するサンプルデータ
例で使用するサンプルデータ
一般的なユースケース
- 動的な日付範囲フィルタリング
- ユーザー別のデータの切り分け
- マルチテナントのデータアクセス
- レポートテンプレート
- データマスキング
materialized view
materialized view は、従来であればストアドプロシージャで行っていた高コストな集計を事前計算するのに最適です。従来のデータベースに慣れている場合は、materialized view を、データがソーステーブルに挿入される際に自動的に変換と集計を行う INSERT トリガー のようなものと考えてください。リフレッシュ可能な materialized view
定期実行するバッチ処理 (夜間実行のストアドプロシージャなど) 向け:外部オーケストレーション
複雑なビジネスロジック、ETL ワークフロー、または複数段階の処理では、言語クライアントを使用して、ClickHouse の外部にロジックを実装することも可能です。アプリケーションコードを使用する
以下は、MySQL のストアドプロシージャを ClickHouse でアプリケーションコードに置き換える場合の比較を左右に並べて示したものです。- MySQL のストアドプロシージャ
- ClickHouseアプリケーションコード
主な違い
- 制御フロー - MySQL のストアドプロシージャでは
IF/ELSEやWHILEループを使用できます。ClickHouse では、このロジックはアプリケーションコード (Python、Java など) に実装します - トランザクション - MySQL は ACID トランザクションのための
BEGIN/COMMIT/ROLLBACKをサポートしています。ClickHouse はトランザクション更新ではなく、追記中心のワークロード向けに最適化された分析データベースです - 更新 - MySQL は
UPDATEステートメントを使用します。ClickHouse では、変更されるデータに対しては ReplacingMergeTree または CollapsingMergeTree を使ったINSERTが推奨されます - 変数と状態 - MySQL のストアドプロシージャでは変数を宣言できます (
DECLARE v_discount) 。ClickHouse では、状態はアプリケーションコードで管理します - エラー処理 - MySQL は
SIGNALと例外ハンドラーをサポートしています。アプリケーションコードでは、使用する言語のネイティブなエラー処理 (try/catch) を使います
ワークフローオーケストレーションツールの活用
- Apache Airflow - ClickHouseクエリの複雑なDAGをスケジュール・監視
- dbt - SQLベースのワークフローでデータを変換
- Prefect/Dagster - モダンなPythonベースのオーケストレーション
- Custom schedulers - Cronジョブ、Kubernetes CronJobs など
- プログラミング言語の機能をフル活用できる
- より優れたエラー処理と再試行ロジック
- 外部システムとのインテグレーション (API、他のデータベース)
- バージョン管理とテスト
- 監視とアラート
- より柔軟なスケジュール設定
ClickHouse におけるプリペアドステートメントの代替手段
ClickHouse には、RDBMS における従来型の「プリペアドステートメント」はありませんが、同じ目的を果たす クエリパラメータ が用意されています。これにより、SQL インジェクションを防ぐ安全なパラメータ化クエリを実現できます。構文
クエリパラメータを定義する方法は2つあります。方法 1: SET を使用する
例: テーブルとデータ
例: テーブルとデータ
方法 2:CLI パラメータを使用する
パラメータの構文
パラメータは次の形式で参照します:{parameter_name: DataType}
parameter_name- パラメータ名 (param_プレフィックスを除く)DataType- パラメータを CAST する先の ClickHouse のデータ型
データ型の例
例で使用するテーブルとサンプルデータ
例で使用するテーブルとサンプルデータ
- 文字列と数値
- 日付と時刻
- Arrays
- Maps
- Identifier
language clients でのクエリパラメータの使用については、関心のある 各言語クライアントのドキュメントを参照してください。
クエリパラメータの制限事項
クエリパラメータは汎用的なテキスト置換ではありません。いくつかの明確な制限があります。- 主にSELECTステートメント向けです - 最も手厚くサポートされているのはSELECTクエリです
- 識別子またはリテラルとして使用できます - 任意のSQLフラグメントを置き換えることはできません
- DDLのサポートは限定的です -
CREATE TABLEではサポートされていますが、ALTER TABLEではサポートされていません
セキュリティのベストプラクティス
ユーザー入力には必ずクエリパラメータを使用してください:MySQL プロトコルのプリペアドステートメント
ClickHouse の MySQL インターフェイス には、プリペアドステートメント (COM_STMT_PREPARE、COM_STMT_EXECUTE、COM_STMT_CLOSE) の最小限のサポートがあります。これは主に、クエリをプリペアドステートメントでラップする Tableau Online のようなツールとの接続を可能にするためのものです。
主な制限事項:
- パラメータのバインドはサポートされていません -
?プレースホルダーにパラメータをバインドして使用することはできません - クエリは保存されますが、
PREPARE時には解析されません - 実装は最小限にとどめられており、特定の BI ツールとの互換性を目的としています
概要
ストアドプロシージャに代わるClickHouseの選択肢
クエリパラメータの用途
クエリパラメータは、次のような用途に使用できます。- SQLインジェクションの防止
- 型安全なパラメータ化クエリ
- アプリケーションでの動的なフィルタリング
- 再利用可能なクエリテンプレート
関連ドキュメント
CREATE FUNCTION- ユーザー定義関数CREATE VIEW- パラメーター化ビューと materialized view- SQL 構文 - クエリパラメータ - パラメータ構文の完全版
- カスケーディング materialized view - 高度な materialized view パターン
- 実行可能 UDF - 外部関数の実行