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
はVIEWにも適用されます。
SQL security
DEFINER
とSQL SECURITY
を使用すると、ビューの基底クエリを実行するときに使用するClickHouseユーザーを指定できます。
SQL SECURITY
には3つの合法的な値があります: DEFINER
、INVOKER
、またはNONE
。DEFINER
句では、既存のユーザーまたはCURRENT_USER
を指定できます。
次の表は、ビューから選択するためにどのユーザーがどの権利を必要とするかを説明します。
SQLセキュリティオプションに関係なく、すべてのケースでGRANT SELECT ON <view>
を持っている必要があることに注意してください。
SQL security option | View | Materialized View |
---|---|---|
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秒でリフレッシュを開始するようになると、1分ごとにリフレッシュを再開します(特に、未実行のリフレッシュのバックログを追いつくために10秒ごとにリフレッシュすることはありません - そのようなバックログはありません)。
さらに、リフレッシュはマテリアライズドビューが作成された後すぐに開始されます。CREATE
クエリでEMPTY
が指定される場合を除きます。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
なしでは、両方のビューは午前0時にリフレッシュを開始します。通常、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
のリフレッシュは、source
がX日目にリフレッシュされるまで待機します(2時間以上かかる場合)。REFRESH EVERY 2 HOUR
はREFRESH EVERY 1 HOUR
に依存しています。
2Hのリフレッシュは1Hのリフレッシュの後、毎時行われます。 例えば、午前0時のリフレッシュの後、午前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
リフレッシュの後に1回リフレッシュされます。つまり、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ミリ秒。refresh_retry_max_backoff_ms
- リフレッシュ試行間の遅延の指数成長の制限。デフォルト: 60000ミリ秒(1分)。
Changing Refresh Parameters
リフレッシュパラメータを変更するには:
これにより、すべてのリフレッシュパラメータが一度に置き換えられます:スケジュール、依存関係、設定、およびAPPEND状態。たとえば、テーブルにDEPENDS ON
があった場合、DEPENDS ON
なしでREFRESH
をMODIFY
を行うと、依存関係が削除されます。
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
と同様に機能します。クエリ結果の代わりに、最新のクエリウォーターマークを取得する短縮形のWATCH
クエリを使用することができます。
Settings
window_view_clean_interval
: 古いデータを解放するためのウィンドウビューのクリーン間隔(秒単位)。システムは、システム時間またはWATERMARK
設定に従って完全にトリガーされていないウィンドウを保持し、他のデータは削除します。window_view_heartbeat_interval
: ウォッチクエリが生きていることを示すためのハートビート間隔(秒単位)。wait_for_window_view_fire_signal_timeout
: イベント時間処理におけるウィンドウビュー発火信号を待つ際のタイムアウト。
Example
クリックログの数を10秒ごとにカウントする必要があるdata
というログテーブルの構造は次の通りです。
まず、10秒インターバルのタムブルウィンドウを持つウィンドウビューを作成します。
次に、WATCH
クエリを使用して結果を取得します。
ログがテーブルdata
に挿入されると、
WATCH
クエリは次の結果を印刷するはずです:
または、出力を別のテーブルにTO
構文を使用して接続することができます。
ClickHouseのステートフルテストの中に追加の例が含まれています(そこでは*window_view*
と名付けられています)。
Window View Usage
ウィンドウビューは以下のシナリオで有用です:
- 監視: 時間に基づいてメトリックログを集計・計算し、対象テーブルに結果を出力します。ダッシュボードは対象テーブルをソーステーブルとして利用できます。
- 分析: 自動的に時間ウィンドウ内のデータを集計・前処理します。これは、多数のログを分析する際に便利です。前処理により、複数のクエリでの再計算が排除され、クエリの遅延が減少します。