マテリアライズドビューを使ってロールアップを構築し、高速な時系列分析を行う
このチュートリアルでは、高ボリュームのイベントテーブルから事前集計されたロールアップを、マテリアライズドビュー を使って維持する方法を説明します。 ここでは、3 つのオブジェクト――生データ用テーブル、ロールアップテーブル、およびロールアップテーブルに自動的に書き込むマテリアライズドビュー――を作成します。
このパターンを使用する状況
次のような場合にこのパターンを使用します:
- 追記専用のイベントストリーム(クリック、ページビュー、IoT、ログ)を扱っている。
- ほとんどのクエリが、時間範囲(分/時間/日ごと)に対する集計処理である。
- すべての生データ行を再スキャンすることなく、常に 1 秒未満の読み取りレイテンシを実現したい。
rawイベントテーブルを作成する
注記
PARTITION BY toYYYYMM(event_time)を指定すると、パーティションを小さく保ち、容易に削除できるようになります。ORDER BY (event_time, user_id)は、時間範囲を指定したクエリおよびセカンダリフィルタをサポートします。LowCardinality(String)は、カテゴリ値を持つディメンションのメモリ消費を抑えます。TTLは 90 日後に生データを自動的に削除します(保持期間の要件に合わせて調整してください)。
ロールアップ(集約)テーブルの設計
時間単位の粒度で事前集計を行います。 最も一般的な分析ウィンドウに合わせて粒度を選択してください。
集約状態(例:AggregateFunction(sum, ...))を保存します。これにより部分集約をコンパクトに表現し、後でマージまたは最終化することができます。
ロールアップへのクエリ実行
読み取り時に状態をマージするか、確定するかを選択できます:
- 読み取り時にマージ
- -Final で最終化
読み取りが常にロールアップにヒットすることが想定される場合は、2つ目のマテリアライズドビューを作成して、_確定済み_の数値を同じ1時間粒度の「プレーン」なMergeTreeテーブルに書き込むことができます。
状態を使用すると柔軟性が高まりますが、確定済みの数値を使用すると読み取りがやや簡潔になります。
最適なパフォーマンスのためにプライマリキーのフィールドでフィルタリングする
EXPLAINコマンドを使用して、インデックスがデータの刈り込みにどのように使用されているかを確認できます:
上記のクエリ実行計画では、3種類のインデックスが使用されています:
MinMaxインデックス、パーティションインデックス、プライマリキーインデックスです。
各インデックスは、プライマリキーで指定されたフィールド (bucket_start, country, event_type) を使用します。
最適なフィルタリングパフォーマンスを実現するには、クエリがプライマリキーフィールドを使用してデータをプルーニングしていることを確認してください。
一般的な構成パターン
- 異なる粒度: 日次ロールアップを追加:
次に2つ目のマテリアライズドビューを作成します:
- 圧縮: raw テーブルのサイズの大きなカラムにコーデックを適用します(例:
Codec(ZSTD(3)))。 - コスト制御:長期保持は生データテーブル側に寄せ、ロールアップは長期間維持する。
- バックフィル:過去データを読み込む場合は、
events_rawに挿入し、マテリアライズドビューにロールアップを自動的に作成させます。既存の行については、適切であればマテリアライズドビュー作成時にPOPULATEを使用するか、INSERT SELECTを使用します。
クリーンアップとデータ保持
- 生データのTTLは(例: 30/90日)に延長しつつ、ロールアップは(例: 1年)と、さらに長期間保持します。
- ティアリングが有効な場合は、古いパーツをより安価なストレージに移動するために TTL to move を使用することもできます。
トラブルシューティング
- マテリアライズドビューが更新されない場合は、データの挿入先がロールアップテーブルではなく events_raw になっていること、またマテリアライズドビューの出力先が正しいこと(
TO events_rollup_1h)を確認してください。 - クエリが遅い場合は、ロールアップにヒットしているか(ロールアップテーブルを直接クエリする)、また時間フィルターがロールアップの粒度に合っているかを確認します。
- バックフィルで不整合が発生していますか?
SYSTEM FLUSH LOGSを実行し、system.query_logとsystem.partsを確認して、INSERT とマージが正しく行われていることを確認してください。