メインコンテンツへスキップ
新しいビューを作成します。ビューには、通常のビューmaterialized viewリフレッシャブルmaterialized view、およびウィンドウビューがあります。

通常ビュー

構文:
CREATE [OR REPLACE] VIEW [IF NOT EXISTS] [db.]table_name [(alias1 [, alias2 ...])] [ON CLUSTER cluster_name]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }]
AS SELECT ...
[COMMENT 'comment']
通常のビューはデータを一切保存しません。アクセスされるたびに、別のテーブルから読み取るだけです。つまり、通常のビューは単なる保存クエリにすぎません。ビューから読み取る際には、この保存クエリが FROM 句内のサブクエリとして使用されます。 例として、次のようなビューを作成したとします。
CREATE VIEW view AS SELECT ...
そして、クエリを記述します:
SELECT a, b, c FROM view
このクエリは、次のサブクエリを使用した場合と完全に等価です。
SELECT a, b, c FROM (SELECT ...)

パラメーター化ビュー

パラメーター化ビューは通常のビューに似ていますが、すぐには評価されないパラメーターを指定して作成できます。これらのビューはテーブル関数として使用でき、その際はビュー名を関数名として、パラメーター値を引数として指定します。
CREATE VIEW view AS SELECT * FROM TABLE WHERE Column1={column1:datatype1} and Column2={column2:datatype2} ...
上記により、以下のようにパラメータを置き換えることでテーブル関数として使用できる、テーブル用のビューが作成されます。
SELECT * FROM view(column1=value1, column2=value2 ...)

Materialized View

CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster_name] [TO[db.]name [(columns)]] [ENGINE = engine] [POPULATE]
[REFRESH ...]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
CREATE OR REPLACE MATERIALIZED VIEW [db.]table_name [ON CLUSTER cluster_name] [TO[db.]name [(columns)]] [ENGINE = engine] [POPULATE]
[REFRESH ...]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
OR REPLACEIF NOT EXISTS は相互に排他的であり、組み合わせると構文エラーになります。

CREATE OR REPLACE MATERIALIZED VIEW

CREATE OR REPLACE MATERIALIZED VIEW は、既存のmaterialized viewと、その内部ストレージテーブル (存在する場合) をアトミックに置き換えます。この操作には、Atomic または Replicated データベースエンジンが必要です。
CREATE OR REPLACE MATERIALIZED VIEW [db.]name [ON CLUSTER cluster]
[TO [db.]target_table]
[ENGINE = engine]
[POPULATE]
[REFRESH ...]
AS SELECT ...
主な動作:
  • TO 句なし: 古い内部テーブルは削除され、新しい内部テーブルが作成されます。POPULATE が指定されていない限り、内部テーブル内の既存データは失われます。
  • TO 句あり: 置き換えられるのはビュー定義のみです。ターゲットテーブルとそのデータには影響しません。
  • REFRESHON CLUSTER、およびすべてのエンジンオプションに対応しています。POPULATEAtomic データベースでのみサポートされ、Replicated データベースでは使用できません (以下の POPULATE に関する注記を参照) 。
  • CREATE VIEW 権限と DROP VIEW 権限が必要です。
CREATE OR REPLACE MATERIALIZED VIEW は、Atomic または Replicated データベースエンジンでのみサポートされます。Ordinary データベースエンジンではサポートされません。
例:
-- 内部テーブルを持つ materialized view を作成する
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    AS SELECT x, sum(y) AS total FROM src GROUP BY x;

-- 新しい定義に置き換える(古い内部テーブルのデータは失われる)
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    AS SELECT x, count() AS cnt FROM src GROUP BY x;

-- POPULATE を使用して既存のソースデータをバックフィルしながら置き換える
CREATE OR REPLACE MATERIALIZED VIEW mv
    ENGINE = MergeTree ORDER BY x
    POPULATE
    AS SELECT x FROM src;

-- 内部テーブル MV を TO テーブル MV に置き換える(ターゲットのデータは保持される)
CREATE OR REPLACE MATERIALIZED VIEW mv TO target
    AS SELECT x FROM src;
materialized view の使い方をステップごとに説明したガイドはこちらです。
materialized view は、対応する SELECT クエリで変換されたデータを格納します。 TO [db].[table] を指定せずに materialized view を作成する場合は、データを格納するためのテーブルエンジンである ENGINE を指定する必要があります。 TO [db].[table] を指定して materialized view を作成する場合は、POPULATE を併用できません。 materialized view は次のように実装されています。SELECT で指定されたテーブルにデータが挿入されると、その挿入データの一部がこの SELECT クエリによって変換され、その結果がビューに挿入されます。
ClickHouse の materialized view では、宛先テーブルへの挿入時にカラム順ではなく カラム名 が使用されます。SELECT クエリの結果に一部のカラム名が存在しない場合、たとえそのカラムが Nullable でなくても、ClickHouse はデフォルト値を使用します。materialized view を使用する場合は、すべてのカラムに別名を付けるのが安全です。ClickHouse の materialized view は、どちらかといえば挿入トリガーのように実装されています。ビューのクエリに集約が含まれている場合、それは新たに挿入されたデータのバッチに対してのみ適用されます。ソーステーブルの既存データに対する変更 (update、delete、drop partition など) によって materialized view が変更されることはありません。ClickHouse の materialized view は、エラー発生時の動作が決定論的ではありません。つまり、すでに書き込まれた block は宛先テーブルに保持されますが、エラー発生後の block は保持されません。デフォルトでは、いずれかのビューへの push に失敗すると、INSERT クエリも失敗し、一部の block が宛先テーブルに書き込まれない可能性があります。これは materialized_views_ignore_errors 設定 (INSERT クエリに対して設定する必要があります) で変更できます。materialized_views_ignore_errors=true を設定すると、ビューへの push 中に発生したエラーはすべて無視され、すべての block が宛先テーブルに書き込まれます。また、system.*_log テーブルでは materialized_views_ignore_errors がデフォルトで true に設定されていることにも注意してください。
POPULATE を指定すると、既存のテーブルデータは、CREATE TABLE ... AS SELECT ... を実行した場合と同様に、作成時にビューへ挿入されます。指定しない場合、クエリにはビューの作成後にテーブルへ挿入されたデータのみが含まれます。ビューの作成中にテーブルへ挿入されたデータはビューに挿入されないため、POPULATE の使用は 推奨しません
POPULATECREATE TABLE ... AS SELECT ... のように動作するため、いくつかの制限があります。
  • Replicated database ではサポートされていません
  • ClickHouse Cloud ではサポートされていません
代わりに、個別に INSERT ... SELECT を使用できます。
SELECT クエリには DISTINCTGROUP BYORDER BYLIMIT を含めることができます。対応する変換は、挿入されるデータの各ブロックごとに独立して実行される点に注意してください。たとえば、GROUP BY が設定されている場合、データは挿入時に集約されますが、それは挿入データの単一のパケット内でのみ行われます。データがその後さらに集約されることはありません。例外は、SummingMergeTree のように、データ集約を独自に実行する ENGINE を使用する場合です。 materialized view が TO [db.]name 構文を使用している場合は、その view を DETACH し、ターゲットテーブルに対して ALTER を実行したあとで、先ほどデタッチした (DETACH) view を ATTACH できます。 materialized view は optimize_on_insert 設定の影響を受ける点に注意してください。データは view に挿入される前にマージされます。 view は通常の table と同じように見えます。たとえば、SHOW TABLES クエリの結果にも表示されます。 view を削除するには、DROP VIEW を使用します。ただし、DROP TABLE も VIEW に対して機能します。

SQL security

DEFINERSQL SECURITY を使うと、ビューの基になるクエリを実行する際に、どの ClickHouse ユーザーを使用するかを指定できます。 SQL SECURITY には、DEFINERINVOKERNONE の 3 つの有効な値があります。DEFINER 句では、既存の任意のユーザー、または CURRENT_USER を指定できます。 次の表は、ビューから読み取るために、どのユーザーにどの権限が必要かを示しています。 なお、SQL security オプションにかかわらず、どの場合でもビューを読み取るには GRANT SELECT ON <view> が引き続き必要です。
SQL security optionViewMaterialized View
DEFINER alicealice は、ビューのソーステーブルに対する SELECT 権限を持っている必要があります。alice は、ビューのソーステーブルに対する SELECT 権限と、ビューのターゲットテーブルに対する INSERT 権限を持っている必要があります。
INVOKERユーザーは、ビューのソーステーブルに対する SELECT 権限を持っている必要があります。materialized view には SQL SECURITY INVOKER を指定できません。
NONE--
SQL SECURITY NONE は非推奨のオプションです。SQL SECURITY NONE を指定してビューを作成する権限を持つユーザーは、任意のクエリを実行できてしまいます。 そのため、このオプションでビューを作成するには GRANT ALLOW SQL SECURITY NONE TO <user> が必要です。
DEFINER/SQL SECURITY が指定されていない場合は、デフォルト値が使用されます。 DEFINER/SQL SECURITY を指定せずにビューがアタッチされた場合、デフォルト値は materialized view では SQL SECURITY NONE、通常のビューでは SQL SECURITY INVOKER です。 既存のビューの SQL security を変更するには、次を使用します。
ALTER TABLE MODIFY SQL SECURITY { DEFINER | INVOKER | NONE } [DEFINER = { user | CURRENT_USER }]

CREATE VIEW test_view
DEFINER = alice SQL SECURITY DEFINER
AS SELECT ...
CREATE VIEW test_view
SQL SECURITY INVOKER
AS SELECT ...

Live View

この機能は非推奨であり、今後削除される予定です。 参考までに、旧ドキュメントはこちらにあります。

リフレッシャブルmaterialized view

CREATE MATERIALIZED VIEW [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
REFRESH EVERY|AFTER interval [OFFSET interval]
[RANDOMIZE FOR interval]
[DEPENDS ON [db.]name [, [db.]name [, ...]]]
[SETTINGS name = value [, name = value [, ...]]]
[APPEND]
[TO[db.]name] [(columns)] [ENGINE = engine]
[EMPTY]
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | NONE }]
AS SELECT ...
[COMMENT 'comment']
ここで、interval は単純なインターバルの列です。
number SECOND|MINUTE|HOUR|DAY|WEEK|MONTH|YEAR
対応するクエリを定期的に実行し、その結果をテーブルに格納します。
  • APPEND が指定されている場合、各リフレッシュでは既存の行を削除せずにテーブルへ行を挿入します。この insert は、通常の INSERT INTO ... SELECT クエリと同様にアトミックではありません。
  • それ以外の場合、各リフレッシュでテーブルの以前の内容はアトミックに置き換えられます。
通常の、リフレッシュ機能のない materialized view との違い:
  • insert trigger はありません。SELECT で指定したテーブルに新しいデータが挿入されても、そのデータがリフレッシャブルmaterialized view に自動的に反映されることは ありません。代わりに、データの挿入は定期実行または手動実行のリフレッシュ時にのみ行われます。
  • SELECT クエリには制約がありません。テーブル関数 (例: url()) 、ビュー、UNION、JOIN はいずれも使用できます。
クエリの REFRESH ... SETTINGS 部分で指定する設定はリフレッシュ設定 (例: refresh_retries) であり、通常の設定 (例: max_threads) とは異なります。通常の設定は、クエリ末尾の SETTINGS で指定できます。

リフレッシュ スケジュール

リフレッシュ スケジュールの例:
REFRESH EVERY 1 DAY -- 毎日深夜0時(UTC)
REFRESH EVERY 1 MONTH -- 毎月1日の深夜0時
REFRESH EVERY 1 MONTH OFFSET 5 DAY 2 HOUR -- 毎月6日の午前2:00
REFRESH EVERY 2 WEEK OFFSET 5 DAY 15 HOUR 10 MINUTE -- 隔週土曜日の午後3:10
REFRESH EVERY 30 MINUTE -- 00:00、00:30、01:00、01:30 など
REFRESH AFTER 30 MINUTE -- 前回のリフレッシュ完了から30分後(時刻への整合なし)
-- REFRESH AFTER 1 HOUR OFFSET 1 MINUTE -- 構文エラー:AFTERにはOFFSETを使用できない
REFRESH EVERY 1 WEEK 2 DAYS -- 9日ごと、曜日や月の特定の日には依存しない;
                            -- 具体的には、日番号(1969-12-29以降)が9の倍数のとき
REFRESH EVERY 5 MONTHS -- 5か月ごと、毎年異なる月になる(12が5で割り切れないため);
                       -- 具体的には、月番号(1970-01以降)が5の倍数のとき
RANDOMIZE FOR は、各リフレッシュの時刻をランダムに調整します。例:
REFRESH EVERY 1 DAY OFFSET 2 HOUR RANDOMIZE FOR 1 HOUR -- 毎日01:30から02:30の間のランダムな時刻に実行
特定のビューでは、同時に実行できる refresh は最大 1 つまでです。たとえば、REFRESH EVERY 1 MINUTE を設定したビューの refresh に 2 分かかる場合、実際の refresh 間隔は 2 分になります。その後、処理が速くなって 10 秒で refresh できるようになれば、再び 1 分ごとの refresh に戻ります。 (つまり、実行されなかった refresh の遅れを取り戻すために 10 秒ごとに refresh されることはありません。そのような未実行分の backlog は存在しません。) さらに、CREATE クエリで EMPTY が指定されていない限り、materialized view の作成直後に refresh が開始されます。EMPTY が指定されている場合、最初の refresh はスケジュールに従って実行されます。

Replicated DB 内で

リフレッシャブルmaterialized view が Replicated database 内にある場合、各レプリカは相互に協調し、スケジュールされた時刻ごとに 1 つのレプリカだけがリフレッシュを実行します。リフレッシュで生成されたデータをすべてのレプリカが参照できるようにするため、ReplicatedMergeTree テーブルエンジンが必要です。 APPEND モードでは、SETTINGS all_replicas = 1 を使用して協調を無効にできます。これにより、各レプリカは互いに独立してリフレッシュを実行します。この場合、ReplicatedMergeTree は必須ではありません。 APPEND 以外のモードでは、協調されたリフレッシュのみがサポートされます。協調なしで行うには、Atomic データベースと CREATE ... ON CLUSTER クエリを使用して、すべてのレプリカにリフレッシャブルmaterialized view を作成してください。 協調は Keeper を通じて行われます。znode path は default_replica_path サーバー設定によって決まります。

リフレッシュの依存関係

DEPENDS ON は、異なるテーブル間のリフレッシュを同期します。たとえば、2 つのリフレッシャブルmaterialized view からなる一連の連鎖があるとします。
CREATE MATERIALIZED VIEW source REFRESH EVERY 1 DAY AS SELECT * FROM url(...)
CREATE MATERIALIZED VIEW destination REFRESH EVERY 1 DAY AS SELECT ... FROM source
DEPENDS ON がない場合、両方のビューは深夜にリフレッシュを開始するため、通常 destination には source の前日のデータが反映されます。依存関係を追加すると:
CREATE MATERIALIZED VIEW destination REFRESH EVERY 1 DAY DEPENDS ON source AS SELECT ... FROM source
この場合、destination の refresh はその日の source の refresh が完了してから初めて開始されるため、destination は最新のデータに基づくことになります。 あるいは、同じ結果は次の方法でも得られます。
CREATE MATERIALIZED VIEW destination REFRESH AFTER 1 HOUR DEPENDS ON source AS SELECT ... FROM source
1 HOUR には、source のリフレッシュ間隔より短い任意の期間を指定できます。依存先のテーブルが、その依存先のいずれよりも高い頻度でリフレッシュされることはありません。これは、実際のリフレッシュ間隔を複数回指定せずに、リフレッシュ可能なビューのチェーンを設定する有効な方法です。 さらにいくつか例を示します。
  • REFRESH EVERY 1 DAY OFFSET 10 MINUTE (destination) は REFRESH EVERY 1 DAY (source) に依存します。
    source のリフレッシュに 10 分以上かかる場合、destination はそれを待ちます。
  • REFRESH EVERY 1 DAY OFFSET 1 HOURREFRESH EVERY 1 DAY OFFSET 23 HOUR に依存します。
    対応するリフレッシュが異なる暦日に発生する場合でも、考え方は上記と同じです。 X+1 日目の destination のリフレッシュは、X 日目の source のリフレッシュを待ちます (2 時間以上かかる場合) 。
  • REFRESH EVERY 2 HOURREFRESH EVERY 1 HOUR に依存します。
    2 HOUR のリフレッシュは、1 時間おきのリフレッシュのうち 1 回おきに 1 HOUR のリフレッシュの後で発生します。たとえば、深夜の リフレッシュの後、次に午前 2 時のリフレッシュの後、という具合です。
  • REFRESH EVERY 1 MINUTEREFRESH EVERY 2 HOUR に依存します。
    destinationsource がリフレッシュされるたびに 1 回、つまり 2 時間ごとにリフレッシュされます。1 MINUTE は実質的に無視されます。
  • REFRESH AFTER 1 HOURREFRESH AFTER 1 HOUR に依存します。
    現時点では、これは推奨されません。
DEPENDS ON は、リフレッシャブルmaterialized view間でのみ機能します。通常のテーブルを DEPENDS ON の一覧に含めると、そのビューはまったくリフレッシュされなくなります (依存関係は ALTER で削除できます。詳細は Changing Refresh Parameters を参照してください) 。

リフレッシュ設定

利用可能なリフレッシュ設定:
  • refresh_retries - リフレッシュクエリが例外で失敗した場合に、再試行する回数を指定します。すべての再試行が失敗した場合は、次にスケジュールされているリフレッシュ時刻までスキップします。0 は再試行なし、-1 は無制限の再試行を意味します。デフォルト: 2。
  • refresh_retry_initial_backoff_ms - refresh_retries が 0 でない場合の、最初の再試行までの待機時間です。以降の再試行では、待機時間が回ごとに 2 倍になり、最大で refresh_retry_max_backoff_ms まで増加します。デフォルト: 100 ms。
  • refresh_retry_max_backoff_ms - リフレッシュ試行の間隔が指数的に増加する際の上限です。デフォルト: 60000 ms (1 分) 。
  • all_replicas - APPEND を使用する Replicated database で、すべてのレプリカが独立してリフレッシュするか、スケジュール時刻ごとに 1 つのレプリカだけがリフレッシュするかを制御します。ビューの作成後は変更できません。デフォルト: false
  • prefer_dependency_replica - ビューに DEPENDS ON がある場合、親のリフレッシュを実行したレプリカが、依存先のリフレッシュ実行でも優先されます。ほかのレプリカは、prefer_dependency_replica_delay_ms の分だけ試行を遅らせます。SharedMergeTree と組み合わせると、レプリケーションラグによって依存リフレッシュの連鎖でデータ欠落が発生するのを防ぐのに役立ちます。デフォルト: false
  • prefer_dependency_replica_delay_ms - prefer_dependency_replica が有効な場合に、優先されないレプリカが依存先のリフレッシュ実行を試みるまでの待機時間です。デフォルト: 2000 ms。

リフレッシュパラメータの変更

既存のリフレッシャブルmaterialized viewのリフレッシュパラメータは、ALTER TABLE ... MODIFY REFRESHを使って変更します。
ALTER TABLE [db.]name MODIFY REFRESH EVERY|AFTER ... [RANDOMIZE FOR ...] [DEPENDS ON ...] [SETTINGS ...]
スケジュール (EVERY または AFTER) の指定は必須です。このステートメントでは、リフレッシュに関するすべてのパラメーター (スケジュール、RANDOMIZE FORDEPENDS ON、およびリフレッシュ設定) が、指定した内容で常に丸ごと置き換えられます。省略した項目は、設定であればデフォルト値に戻され、依存関係やランダム化であれば削除されます。
  • リフレッシュ設定のみを変更するには (例: refresh_retries) 、現在のスケジュールを再度指定してください。
    ALTER TABLE rmv MODIFY REFRESH EVERY 1 HOUR SETTINGS refresh_retries = 5;
    
  • ALTER TABLE ... MODIFY SETTING refresh_retries = ... は materialized view ではサポートされていません。必ず MODIFY REFRESH を使用してください。
  • APPEND の追加または削除はサポートされていません。
  • all_replicas 設定は作成後に変更できません。
例:
-- スケジュールを変更し、既存の設定と依存関係を削除する。
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE;

-- スケジュールを変更し、再試行の動作を調整する。
ALTER TABLE rmv MODIFY REFRESH EVERY 30 MINUTE
SETTINGS refresh_retries = 5,
         refresh_retry_initial_backoff_ms = 500,
         refresh_retry_max_backoff_ms = 60000;

-- 期間を変更しながら依存関係を維持する。
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR DEPENDS ON other_rmv;

-- `DEPENDS ON` を省略して依存関係を削除する。
ALTER TABLE rmv MODIFY REFRESH EVERY 6 HOUR;

その他の操作

すべてのリフレッシャブルmaterialized viewの状態は、テーブルsystem.view_refreshesで確認できます。特に、リフレッシュの進行状況 (実行中の場合) 、前回および次回のリフレッシュ時刻、リフレッシュが失敗した場合の例外メッセージが含まれます。 手動でリフレッシュを停止、開始、トリガー、またはキャンセルするには、SYSTEM STOP|START|REFRESH|WAIT|CANCEL VIEWを使用します。 リフレッシュの完了を待機するには、SYSTEM WAIT VIEWを使用します。特に、ビューの作成後に初回リフレッシュが完了するのを待つ際に便利です。
豆知識: リフレッシュクエリは、現在リフレッシュ中のビューから読み取ることができ、その際にはリフレッシュ前のバージョンのデータを参照します。つまり、Conway’s Game of Life を実装できます: https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==

ウィンドウビュー

これは実験的な機能であり、今後のリリースで後方互換性のない変更が行われる可能性があります。ウィンドウビュー と WATCH クエリを使用するには、allow_experimental_window_view 設定を有効にしてください。set allow_experimental_window_view = 1 コマンドを実行します。
CREATE WINDOW VIEW [IF NOT EXISTS] [db.]table_name [TO [db.]table_name] [INNER ENGINE engine] [ENGINE engine] [WATERMARK strategy] [ALLOWED_LATENESS interval_function] [POPULATE]
AS SELECT ...
GROUP BY time_window_function
[COMMENT 'comment']
ウィンドウビュー は、時間ウィンドウ単位でデータを集約し、ウィンドウの発火準備が整うと結果を出力できます。部分的な集約結果は、レイテンシを低減するために内部テーブル (または指定したテーブル) に保存され、処理結果を指定したテーブルに送信したり、WATCH クエリを使用して通知を送信したりできます。 ウィンドウビュー の作成は、MATERIALIZED VIEW の作成に似ています。ウィンドウビュー では、中間データを保存するための内部ストレージエンジンが必要です。内部ストレージは INNER ENGINE 句を使用して指定でき、ウィンドウビュー はデフォルトの内部エンジンとして AggregatingMergeTree を使用します。 TO [db].[table] なしで ウィンドウビュー を作成する場合は、データを保存するためのテーブルエンジンである ENGINE を指定する必要があります。

時間ウィンドウ関数

時間ウィンドウ関数は、レコードのウィンドウ境界の下限と上限を取得するために使用します。ウィンドウビュー は時間ウィンドウ関数と併せて使用する必要があります。

時間属性

ウィンドウビューは、処理時間イベント時間の両方をサポートしています。 処理時間では、ウィンドウビューはローカルマシンの時刻に基づいて結果を生成し、デフォルトで使用されます。これは最もシンプルで分かりやすい時間の概念ですが、決定性は保証されません。処理時間属性は、時間ウィンドウ関数の time_attr にテーブルのカラムを指定するか、now() 関数を使用することで定義できます。次のクエリは、処理時間を使用するウィンドウビューを作成します。
CREATE WINDOW VIEW wv AS SELECT count(number), tumbleStart(w_id) as w_start from date GROUP BY tumble(now(), INTERVAL '5' SECOND) as w_id
イベント時刻 とは、各イベントが生成元のデバイスで実際に発生した時刻のことです。この時刻は通常、レコードの生成時にレコード内へ埋め込まれます。イベント時刻処理を行うことで、イベントの順序が前後していたり、到着が遅れたりする場合でも、一貫した結果を得られます。ウィンドウビュー は、WATERMARK 構文を使用してイベント時刻処理をサポートします。 ウィンドウビュー には、3 つのウォーターマーク戦略があります。
  • STRICTLY_ASCENDING: これまでに観測された最大のタイムスタンプのウォーターマークを出力します。タイムスタンプが最大タイムスタンプより小さい行は、遅延データとは見なされません。
  • ASCENDING: これまでに観測された最大のタイムスタンプから 1 を引いたウォーターマークを出力します。タイムスタンプが最大タイムスタンプ以下の行は、遅延データとは見なされません。
  • BOUNDED: WATERMARK=INTERVAL。これまでに観測された最大のタイムスタンプから指定した遅延を引いたウォーターマークを出力します。
以下のクエリは、WATERMARK を使用して ウィンドウビュー を作成する例です。
CREATE WINDOW VIEW wv WATERMARK=STRICTLY_ASCENDING AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
CREATE WINDOW VIEW wv WATERMARK=ASCENDING AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
CREATE WINDOW VIEW wv WATERMARK=INTERVAL '3' SECOND AS SELECT count(number) FROM date GROUP BY tumble(timestamp, INTERVAL '5' SECOND);
デフォルトでは、ウォーターマークに達するとウィンドウが発火し、ウォーターマークより遅れて到着した要素は破棄されます。ウィンドウビュー では、ALLOWED_LATENESS=INTERVAL を設定することで遅延イベントの処理をサポートします。遅延処理の例を次に示します。
CREATE WINDOW VIEW test.wv TO test.dst WATERMARK=ASCENDING ALLOWED_LATENESS=INTERVAL '2' SECOND AS SELECT count(a) AS count, tumbleEnd(wid) AS w_end FROM test.mt GROUP BY tumble(timestamp, INTERVAL '5' SECOND) AS wid;
遅延発火によって出力される要素は、以前の計算結果に対する更新結果として扱う必要があることに注意してください。ウィンドウビュー は、window の終了時に発火するのではなく、遅延イベントが到着すると即座に発火します。そのため、同じ window に対して複数の出力が生成されます。ユーザーは、これらの重複した結果を考慮するか、重複排除する必要があります。 ウィンドウビュー で指定した SELECT クエリは、ALTER TABLE ... MODIFY QUERY ステートメントを使用して変更できます。新しい SELECT クエリによって得られるデータ構造は、TO [db.]name 句の有無にかかわらず、元の SELECT クエリと同じである必要があります。中間状態は再利用できないため、現在の window 内のデータは失われることに注意してください。

新しいウィンドウの監視

ウィンドウビュー は、変更を監視するための WATCH クエリをサポートしているほか、TO 構文を使用して結果をテーブルに出力することもできます。
WATCH [db.]window_view
[EVENTS]
[LIMIT n]
[FORMAT format]
クエリを終了するまでに受け取る更新回数は、LIMIT で指定できます。EVENTS 句を使うと、WATCH クエリの簡易形式を利用できます。この場合、クエリ結果の代わりに、最新のクエリのウォーターマークだけが返されます。

設定

  • window_view_clean_interval: 古くなったデータを解放するための、ウィンドウビュー のクリーンアップ間隔 (秒) です。システム時刻または WATERMARK 設定に基づき、まだ完全にはトリガーされていないウィンドウは保持され、それ以外のデータは削除されます。
  • window_view_heartbeat_interval: watchクエリが動作中であることを示すハートビート間隔 (秒) です。
  • wait_for_window_view_fire_signal_timeout: イベント時刻処理において、ウィンドウビュー の fire signal を待機する際のタイムアウトです。

data という名前のログテーブルで、10秒ごとのクリックログ数を集計する必要があるとします。テーブル構造は次のとおりです。
CREATE TABLE data ( `id` UInt64, `timestamp` DateTime) ENGINE = Memory;
まず、10秒間隔のタンブルウィンドウを持つウィンドウビューを作成します。
CREATE WINDOW VIEW wv as select count(id), tumbleStart(w_id) as window_start from data group by tumble(timestamp, INTERVAL '10' SECOND) as w_id
次に、結果を取得するには WATCH クエリを使用します。
WATCH wv
data テーブルにログが挿入されると、
INSERT INTO data VALUES(1,now())
WATCH クエリの結果は次のように表示されます:
┌─count(id)─┬────────window_start─┐
│         1 │ 2020-01-14 16:56:40 │
└───────────┴─────────────────────┘
あるいは、TO構文を使用して、出力を別のテーブルに関連付けることもできます。
CREATE WINDOW VIEW wv TO dst AS SELECT count(id), tumbleStart(w_id) as window_start FROM data GROUP BY tumble(timestamp, INTERVAL '10' SECOND) as w_id
その他の例は、ClickHouse のステートフルテスト内にあります (そこでは *window_view* という名前です) 。

ウィンドウビュー の使用法

ウィンドウビュー は、次のようなシナリオで役立ちます。
  • 監視: ログのメトリクスを時間ごとに集計・計算し、その結果をターゲットテーブルに出力します。ダッシュボードでは、ターゲットテーブルをソーステーブルとして使用できます。
  • 分析: 時間ウィンドウ内のデータを自動的に集計して前処理します。これは、大量のログを分析する場合に役立ちます。前処理により、複数のクエリで同じ計算を繰り返す必要がなくなり、クエリのレイテンシが低減されます。

一時ビュー

ClickHouse は、一時ビューをサポートしており、次のような特性があります (該当する場合は一時テーブルと同様です) 。
  • セッション存続期間 一時ビューは現在のセッション中にのみ存在します。セッションが終了すると自動的に削除されます。
  • データベースなし 一時ビューをデータベース名で修飾することはできません。一時ビューはデータベースの外側 (セッションのネームスペース) に存在します。
  • レプリケートされない / ON CLUSTER なし 一時オブジェクトはセッションローカルであり、ON CLUSTER を付けて作成することはできません
  • 名前解決 一時オブジェクト (テーブルまたはビュー) が永続オブジェクトと同じ名前を持ち、クエリがデータベース名を付けずにその名前を参照した場合は、一時オブジェクトが使用されます。
  • 論理オブジェクト (ストレージなし) 一時ビューが保持するのは SELECT テキストのみです (内部的には View ストレージを使用します) 。データは永続化されず、INSERT も受け付けません。
  • Engine 句 ENGINE を指定する必要はありませんENGINE = View として指定した場合も、無視されるか、同じ論理ビューとして扱われます。
  • セキュリティ / 権限 一時ビューを作成するには CREATE TEMPORARY VIEW 権限が必要です。この権限は CREATE VIEW によって暗黙的に付与されます。
  • SHOW CREATE 一時ビューの DDL を表示するには、SHOW CREATE TEMPORARY VIEW view_name; を使用します。

構文

CREATE TEMPORARY VIEW [IF NOT EXISTS] view_name AS <select_query>
OR REPLACE は、一時テーブルとの整合性を保つため、一時ビューでは サポートされていません。一時ビューを「置き換える」必要がある場合は、いったん削除してから再作成してください。

一時ソーステーブルを作成し、その上に一時ビューを作成します。
CREATE TEMPORARY TABLE t_src (id UInt32, val String);
INSERT INTO t_src VALUES (1, 'a'), (2, 'b');

CREATE TEMPORARY VIEW tview AS
SELECT id, upper(val) AS u
FROM t_src
WHERE id <= 2;

SELECT * FROM tview ORDER BY id;
DDLを表示します:
SHOW CREATE TEMPORARY VIEW tview;
削除:
DROP TEMPORARY VIEW IF EXISTS tview;  -- 一時ビューは TEMPORARY TABLE 構文でドロップします

使用不可 / 制限事項

  • CREATE OR REPLACE TEMPORARY VIEW ...使用できません (DROP + CREATE を使用してください) 。
  • CREATE TEMPORARY MATERIALIZED VIEW ... / WINDOW VIEW使用できません
  • CREATE TEMPORARY VIEW db.view AS ...使用できません (データベース修飾子は指定できません) 。
  • CREATE TEMPORARY VIEW view ON CLUSTER 'name' AS ...使用できません (一時オブジェクトはセッションローカルです) 。
  • POPULATE, REFRESH, TO [db.table], 内部エンジン、および MV 固有の句は、一時ビューには 適用されません

分散クエリに関する注意事項

一時ビューは単なる定義にすぎず、受け渡すデータはありません。一時ビューが一時テーブル (たとえば Memory) を参照している場合、そのデータは一時テーブルと同様に、分散クエリの実行中にリモートサーバーへ転送されることがあります。

-- セッションスコープのインメモリテーブル
CREATE TEMPORARY TABLE temp_ids (id UInt64) ENGINE = Memory;

INSERT INTO temp_ids VALUES (1), (5), (42);

-- 一時テーブル上のセッションスコープビュー(純粋に論理的)
CREATE TEMPORARY VIEW v_ids AS
SELECT id FROM temp_ids;

-- 'test' をクラスター名に置き換えてください。
-- GLOBAL JOIN を使用すると、ClickHouse は小さい結合側(v_ids 経由の temp_ids)を
-- 左側を実行するすべてのリモートサーバーに*送信*します。
SELECT count()
FROM cluster('test', system.numbers) AS n
GLOBAL ANY INNER JOIN v_ids USING (id)
WHERE n.number < 100;

最終更新日 2026年6月10日