CREATE VIEW
新しいビューを作成します。ビューは、通常の、物化つい、リフレッシュ可能な物化ビュー、および ウィンドウ(リフレッシュ可能な物化ビューとウィンドウビューは実験的機能です)として作成できます。
Normal View
構文:
通常のビューはデータを保存していません。アクセスのたびに別のテーブルから読み取るだけです。言い換えれば、通常のビューは保存されたクエリに過ぎません。ビューから読み取るとき、この保存されたクエリがFROM句のサブクエリとして使用されます。
例として、次のようにビューを作成したと仮定しましょう:
そして、クエリを次のように書きます:
このクエリは、サブクエリを使用した場合と完全に同等です:
Parameterized View
パラメータ化されたビューは通常のビューに似ていますが、すぐには解決されないパラメータと共に作成することができます。これらのビューは、テーブル関数と共に使用でき、ビューの名前を関数名として、パラメータ値を引数として指定します。
上記は、パラメータを次のように置き換えることで、テーブル関数として使用できるビューを作成します。
Materialized View
物化ビューの使用に関する手順ガイドです。
物化ビューは、対応するSELECTクエリによって変換されたデータを格納します。
TO [db].[table]
なしで物化ビューを作成する場合、データを格納するためのテーブルエンジンであるENGINE
を指定する必要があります。
TO [db].[table]
を使用して物化ビューを作成する場合、POPULATE
を同時に使用することはできません。
物化ビューは次のように実装されます: SELECT
で指定されたテーブルにデータを挿入するとき、挿入されたデータの一部はこのSELECT
クエリによって変換され、結果はビューに挿入されます。
ClickHouseの物化ビューは、データを宛先テーブルに挿入する際にカラム名を使用します。SELECT
クエリの結果に存在しないカラム名がある場合、ClickHouseはデフォルト値を使用します。たとえカラムがNullableでなくても、これは変わりません。物化ビューを使用する際は、各カラムにエイリアスを追加するのが安全な作業です。
ClickHouseの物化ビューは、挿入トリガーとしてより実装されています。ビュークエリに集約が含まれている場合、それは新しく挿入されたデータのバッチにのみ適用されます。基のテーブルの既存のデータに対する変更(更新、削除、パーティションのドロップなど)は、物化ビューを変更しません。
ClickHouseの物化ビューは、エラーが発生した場合に決定的な動作を持ちません。これは、すでに書き込まれたブロックは宛先テーブルに保持されますが、エラー以降のすべてのブロックが保持されないことを意味します。
デフォルトでは、いずれかのビューへのプシュが失敗すると、INSERTクエリも失敗し、一部のブロックが宛先テーブルに書き込まれない可能性があります。これをmaterialized_views_ignore_errors
設定を使用して変更できます(この設定はINSERT
クエリに対して設定する必要があります)。materialized_views_ignore_errors=true
を設定すると、ビューへのプッシュ中のすべてのエラーが無視され、すべてのブロックが宛先テーブルに書き込まれます。
また、materialized_views_ignore_errors
は、デフォルトでsystem.*_log
テーブルに対してtrue
に設定されています。
POPULATE
を指定すると、既存のテーブルデータがビューに挿入され、CREATE TABLE ... AS SELECT ...
を行うかのようになります。そうでない場合、クエリにはビュー作成後にテーブルに挿入されたデータのみが含まれます。データがビュー作成中にテーブルに挿入されるため、POPULATE
の使用は推奨しません。
POPULATE
はCREATE TABLE ... AS SELECT ...
のように機能するため、制限があります:
- レプリケーションデータベースではサポートされていません。
- ClickHouseクラウドではサポートされていません。
代わりに、別のINSERT ... SELECT
を使用できます。
SELECT
クエリは、DISTINCT
、GROUP BY
、ORDER BY
、LIMIT
を含めることができます。対応する変換は挿入されたデータの各ブロックに対して独立して実行されることに注意してください。たとえば、GROUP BY
が設定されている場合、データは挿入中に集約されますが、挿入されたデータの単一のパケット内のみです。データはさらに集約されることはありません。例外は、SummingMergeTree
のようにデータ集約を独自に実行するENGINE
を使用するときです。
物化ビューに対するALTERクエリの実行には制限があります。たとえば、SELECT
クエリを更新することはできないため、不便な場合があります。物化ビューがTO [db.]name
構造を使用している場合、ビューをDETACH
し、ターゲットテーブルに対してALTER
を実行し、その後以前にDETACH
したビューをATTACH
できます。
物化ビューはoptimize_on_insert設定の影響を受けることに注意してください。データはビューへの挿入前にマージされます。
ビューは通常のテーブルと同様に見えます。たとえば、SHOW TABLES
クエリの結果にリストされます。
ビューを削除するには、DROP VIEWを使用します。DROP TABLE
もビューに対して機能します。
SQL security
DEFINER
およびSQL SECURITY
を使用すると、ビューの基となるクエリを実行する際に使用するClickHouseユーザーを指定できます。
SQL SECURITY
には3つの合法的な値があります: DEFINER
、INVOKER
、またはNONE
。DEFINER
句では、任意の既存のユーザーまたはCURRENT_USER
を指定できます。
以下の表は、ビューから選択するために必要なユーザーごとの権限を説明します。
SQLセキュリティオプションに関係なく、読み取るには常にGRANT SELECT ON <view>
が必要であることに注意してください。
SQLセキュリティオプション | ビュー | 物化ビュー |
---|---|---|
DEFINER alice | alice はビューのソーステーブルに対してSELECT 権限を持っている必要があります。 | alice はビューのソーステーブルに対してSELECT 権限を持っていて、ビューのターゲットテーブルに対してINSERT 権限も必要です。 |
INVOKER | ユーザーはビューのソーステーブルに対してSELECT 権限を持っている必要があります。 | SQL SECURITY INVOKER は物化ビューに対して指定できません。 |
NONE | - | - |
SQL SECURITY NONE
は非推奨のオプションです。SQL SECURITY NONE
でビューを作成する権限を持つユーザーは、任意のクエリを実行することができます。
したがって、このオプションでビューを作成するには、GRANT ALLOW SQL SECURITY NONE TO <user>
が必要です。
DEFINER
/SQL SECURITY
が指定されていない場合、デフォルト値が使用されます:
SQL SECURITY
: 通常のビューのためにINVOKER
、物化ビューのためにDEFINER
(設定によって構成可能)DEFINER
:CURRENT_USER
(設定によって構成可能)
DEFINER
/SQL SECURITY
が指定されていないビューがアタッチされている場合、物化ビューに対するデフォルト値はSQL SECURITY NONE
、通常のビューに対するデフォルト値はSQL SECURITY INVOKER
です。
既存のビューのSQLセキュリティを変更するには、次のように使用します。
Examples
Live View
この機能は非推奨であり、将来的に削除される予定です。
お手数ですが、旧ドキュメントはこちらにあります。
Refreshable Materialized View
ここで、interval
は単純なインターバルのシーケンスです:
定期的に対応するクエリを実行し、その結果をテーブルに格納します。
- クエリが
APPEND
と言った場合、各リフレッシュは既存の行を削除せずにテーブルに行を挿入します。挿入は原子的ではなく、通常のINSERT SELECTと同様です。 - さもなくば、各リフレッシュはテーブルの以前の内容を原子的に置き換えます。
リフレッシュ可能な物化ビューの通常の非リフレッシュ可能な物化ビューとの違い:
- 挿入トリガーがありません。つまり、
SELECT
で指定されたテーブルに新しいデータが挿入されると、自動的にリフレッシュ可能な物化ビューにプッシュされません。定期的なリフレッシュはクエリ全体を実行します。 SELECT
クエリに制限はありません。テーブル関数(例:url()
)、ビュー、UNION、JOINがすべて許可されています。
REFRESH ... SETTINGS
部分のクエリ内の設定はリフレッシュ設定(例:refresh_retries
)であり、通常の設定(例:max_threads
)とは異なります。通常の設定は、クエリの最後にSETTINGS
を使用して指定できます。
Refresh Schedule
リフレッシュスケジュールの例:
RANDOMIZE FOR
は、各リフレッシュの時間をランダムに調整します。例:
与えられたビューに対しては、同時に1回だけリフレッシュを実行できます。例えば、REFRESH EVERY 1 MINUTE
のビューがリフレッシュに2分かかると、リフレッシュは2分ごとに行われます。高速になり、10秒でリフレッシュを開始すると、再度毎分リフレッシュされます(特に、バックログのリフレッシュを追いかけるために毎10秒リフレッシュされるわけではない - そのようなバックログはありません)。
加えて、物化ビューが作成された直後にリフレッシュが開始されます。CREATE
クエリにEMPTY
が指定されている場合、最初のリフレッシュはスケジュールに従って行われます。
In Replicated DB
リフレッシュ可能な物化ビューがレプリケートデータベースにある場合、レプリカは調整し合い、毎回のスケジュールで1つのレプリカだけがリフレッシュを実行します。ReplicatedMergeTreeテーブルエンジンが必要であり、すべてのレプリカはリフレッシュで生成されたデータを確認します。
APPEND
モードでは、SETTINGS all_replicas = 1
を使用して調整を無効にできます。これにより、レプリカは互いに独立してリフレッシュを行います。この場合、ReplicatedMergeTreeは必要ありません。
非APPEND
モードでは、調整されたリフレッシュのみがサポートされています。非調整の場合は、AtomicデータベースおよびCREATE ... ON CLUSTER
クエリを使用して、すべてのレプリカにリフレッシュ可能な物化ビューを作成します。
調整はKeeperを介して行われます。znodeのパスはdefault_replica_pathサーバー設定によって決定されます。
Dependencies
DEPENDS ON
は異なるテーブルのリフレッシュを同期させます。例として、次のような2つのリフレッシブルな物化ビューのチェーンを考えてみてください:
DEPENDS ON
がない場合、両方のビューは真夜中にリフレッシュを開始し、destination
は通常、source
の昨日のデータを見ます。依存関係を追加すると:
この場合、destination
のリフレッシュはその日のsource
のリフレッシュが終了した後にのみ開始されるため、destination
は新しいデータに基づいて更新されます。
あるいは、次のように実現できます:
ここで、1 HOUR
はsource
のリフレッシュ期間より短い任意の期間で構いません。依存しているテーブルは、その依存関係よりも頻繁にはリフレッシュされません。これは、実際のリフレッシュ期間を1回以上指定することなく、リフレッシュ可能なビューのチェーンを設定するための有効な方法です。
他のいくつかの例:
REFRESH EVERY 1 DAY OFFSET 10 MINUTE
(destination
)はREFRESH EVERY 1 DAY
(source
)に依存します。
source
のリフレッシュが10分以上かかる場合、destination
はそれを待ちます。REFRESH EVERY 1 DAY OFFSET 1 HOUR
はREFRESH EVERY 1 DAY OFFSET 23 HOUR
に依存します。
上記のように、対応するリフレッシュが異なるカレンダーの日に発生しても、destination
のリフレッシュはX+1の日でsource
のリフレッシュがXの日(2時間以上かかる場合)の完了を待ちます。REFRESH EVERY 2 HOUR
はREFRESH EVERY 1 HOUR
に依存します。
2 HOURリフレッシュは、毎時リフレッシュした後に行われます(真夜中のリフレッシュ後、次の2時のリフレッシュ後など)。REFRESH EVERY 1 MINUTE
はREFRESH EVERY 2 HOUR
に依存します。
REFRESH AFTER 1 MINUTE
はREFRESH EVERY 2 HOUR
に依存します。
REFRESH AFTER 1 MINUTE
はREFRESH AFTER 2 HOUR
に依存します。
destination
は、毎回のsource
リフレッシュの後、すなわち2時間ごとに更新されます。1 MINUTE
は実質的に無視されます。REFRESH AFTER 1 HOUR
はREFRESH AFTER 1 HOUR
に依存します。
現在これは推奨されていません。
DEPENDS ON
は、リフレッシュ可能な物化ビューの間でのみ機能します。DEPENDS ON
リストに通常のテーブルを記載すると、そのビューは永遠にリフレッシュしなくなります(依存関係はALTER
によって削除できます)。
Settings
利用可能なリフレッシュ設定:
refresh_retries
- リフレッシュクエリが例外で失敗した場合のリトライ回数。すべてのリトライが失敗した場合、次のスケジュールされたリフレッシュ時間にスキップします。0はリトライなし、-1は無限リトライを意味します。デフォルト:0。refresh_retry_initial_backoff_ms
- 最初のリトライ前の遅延で、refresh_retries
がゼロでない場合。各次のリトライが遅延を2倍にし、refresh_retry_max_backoff_ms
まで成長します。デフォルト:100 ms。refresh_retry_max_backoff_ms
- リフレッシュ試行間の遅延の指数的成長の制限。デフォルト:60000 ms(1分)。
Changing Refresh Parameters
リフレッシュパラメータを変更するには:
これにより、すべてのリフレッシュパラメータ(スケジュール、依存関係、設定、およびAPPENDの有無)が一度に置き換えられます。たとえば、テーブルにDEPENDS ON
があった場合、DEPENDS ON
なしでMODIFY REFRESH
を行うと、依存関係が削除されます。
Other operations
すべてのリフレッシュ可能な物化ビューの状態は、テーブルsystem.view_refreshes
で利用できます。特に、リフレッシュの進行状況(実行中の場合)、最後のリフレッシュ時間、次のリフレッシュ時間、リフレッシュが失敗した場合の例外メッセージが含まれます。
リフレッシュを手動で停止、開始、トリガー、またはキャンセルするにはSYSTEM STOP|START|REFRESH|WAIT|CANCEL VIEW
を使用します。
リフレッシュの完了を待つにはSYSTEM WAIT VIEW
を使用します。特に、ビュー作成後の初期リフレッシュの待機に役立ちます。
面白い事実:リフレッシュクエリは、リフレッシュされているビューから読み取ることが許可されています。つまり、データのリフレッシュ前のバージョンを見ることができます。これにより、コンウェイのライフゲームを実装できます:https://pastila.nl/?00021a4b/d6156ff819c83d490ad2dcec05676865#O0LGWTO7maUQIA4AcGUtlA==
Window View
これは実験的な機能であり、将来のリリースで後方互換性のない方法で変更される可能性があります。ウィンドウビューとWATCH
クエリの使用を有効にするには、allow_experimental_window_view設定を使用します。コマンド set allow_experimental_window_view = 1
を入力してください。
ウィンドウビューは、時間ウィンドウでデータを集約し、ウィンドウが発火する準備が整ったときにその結果を出力できます。レイテンシを削減するために中間集約結果を内側(または指定された)テーブルに保存し、指定されたテーブルに処理結果をプッシュしたり、WATCHクエリを使用してプッシュ通知を行ったりできます。
ウィンドウビューの作成は、MATERIALIZED VIEW
の作成に似ています。ウィンドウビューには中間データを保存するための内側ストレージエンジンが必要です。内側ストレージは、INNER ENGINE
句を使用して指定できます。デフォルトの内側エンジンはAggregatingMergeTree
です。
TO [db].[table]
なしでウィンドウビューを作成する場合、データを格納するためのテーブルエンジンであるENGINE
を指定する必要があります。
Time Window Functions
時間ウィンドウ関数は、レコードの下限および上限ウィンドウを取得するために使用されます。ウィンドウビューは、時間ウィンドウ関数と共に使用する必要があります。
TIME ATTRIBUTES
ウィンドウビューは処理時間とイベント時間の処理をサポートしています。
処理時間は、ウィンドウビューがローカルマシンの時間に基づいて結果を生成できるようにし、デフォルトで使用されます。これは最も直接的な時間の定義ですが、決定論的ではありません。処理時間属性は、時間ウィンドウ関数のtime_attr
をテーブルのカラムに設定することによって、またはnow()
関数を使用することによって定義できます。以下のクエリは、処理時間でウィンドウビューを作成します。
イベント時間は、各個別のイベントが生成装置で発生した時刻を指します。この時間は通常、生成されるときにレコードに埋め込まれます。イベント時間処理は、順序が乱れたイベントや遅延イベントが発生した場合でも一貫した結果を可能にします。ウィンドウビューはWATERMARK
構文を使用することで、イベント時間処理をサポートします。
ウィンドウビューは3つのウォーターマーク戦略を提供します:
STRICTLY_ASCENDING
:これまでに観測された最大のタイムスタンプのウォーターマークを発行します。最大タイムスタンプよりも小さいタイムスタンプを持つ行は遅れたものではありません。ASCENDING
:これまでに観測された最大のタイムスタンプのウォーターマークを発行しますが、1を引きます。最大タイムスタンプと同じか小さいタイムスタンプを持つ行は遅れたものではありません。BOUNDED
:WATERMARK=INTERVAL。指定した遅延を引いた最大の観測されたタイムスタンプをウォーターマークとして発行します。
以下のクエリは、WATERMARK
を使用してウィンドウビューを作成する例です:
デフォルトでは、ウォーターマークが到達したときにウィンドウが発火し、ウォーターマークを超えて到着した要素は破棄されます。ウィンドウビューは、ALLOWED_LATENESS=INTERVAL
を設定することで遅延イベント処理をサポートします。遅延処理の一例は以下の通りです:
遅れて発生した要素から出力される結果は、以前の計算の更新された結果として処理されるべきです。ウィンドウの終了時ではなく、遅延イベントが到着したときにウィンドウビューは即座に発火します。このため、同じウィンドウに複数の出力が結果として生じます。ユーザーはこれらの重複結果を考慮するか、重複排除を行う必要があります。
ウィンドウビューで指定されたSELECT
クエリを変更するには、ALTER TABLE ... MODIFY QUERY
ステートメントを使用します。更新されたSELECT
クエリから得られるデータ構造は、TO [db.]name
句の有無にかかわらず元のSELECT
クエリと同様である必要があります。中間状態が再利用できないため、現在のウィンドウのデータは失われることに注意してください。
Monitoring New Windows
ウィンドウビューは、変更を監視するためにWATCHクエリをサポートします。また、結果をテーブルに出力するためにTO
構文を使用できます。
WATCH
クエリは、LIVE VIEW
と似た動作をします。受信する更新の数を指定するためにLIMIT
を設定できます。EVENTS
句を使用すると、クエリの結果の代わりに最新のクエリのウォーターマークのみを取得する短い形式のWATCH
クエリを取得できます。
Settings
window_view_clean_interval
: 古いデータを解放するためのウィンドウビューのクリーン間隔(秒単位)。システムは、システム時間またはWATERMARK
設定に従って完全にトリガーされていないウィンドウを保持し、その他のデータは削除されます。window_view_heartbeat_interval
: ウォッチクエリが生存していることを示すためのハートビート間隔(秒単位)。wait_for_window_view_fire_signal_timeout
: イベント時間処理におけるウィンドウビューの発火信号を待つためのタイムアウト。
Example
クリックログを10秒ごとにカウントする必要があると仮定し、ログテーブルの構造は次のようになります。
まず、10秒間隔のタンブルウィンドウでウィンドウビューを作成します。
次に、WATCH
クエリを使用して結果を取得します。
データテーブルにログが挿入されるとき、
WATCH
クエリは、以下の結果を印刷するはずです:
代わりに、TO
構文を使用して出力を別のテーブルに接続できます。
追加の例は、ClickHouseのステートフルテスト群の中にあります(それらは*window_view*
という名前です)。
Window View Usage
ウィンドウビューは、以下のシナリオで役立ちます:
- 監視: 時間ごとにメトリクスログを集約し計算し、結果をターゲットテーブルに出力します。ダッシュボードはターゲットテーブルをソーステーブルとして使用できます。
- 分析: 時間ウィンドウ内でデータを自動的に集約し前処理します。これは、多くのログを分析する際に便利です。前処理は、複数のクエリでの計算の繰り返しを排除し、クエリのレイテンシを削減します。