Map(LowCardinality(String), String) カラムに保存されます。ClickHouse は厳密に型付けされた JSON 型 もサポートしており、ClickStack では Map の代わりにこれを使用するためのベータサポートも提供されています。
一般的なオブザーバビリティのワークロードでは、デフォルトの Map ベースのスキーマをそのまま使用することを推奨します。 JSON 型は、属性キーの種類が少なく、かつ安定しているワークロードで評価したいユーザー向けに利用できますが、一般用途向けの推奨スキーマではありません。
Map が推奨されるデフォルトである理由
Map(LowCardinality(String), String) は、キーと値を単一の構造として格納します。従来の Map の欠点は、1 つのキーを読み取るだけでも map カラム全体を読む必要があったことです。しかし、これはもう当てはまりません。現在の ClickHouse は bucketed map serialization をサポートしており、map を複数の bucket に分割することで、クエリは必要な bucket だけを読み取れます。さらに、map のキーと値に対する テキスト索引 を組み合わせることで、つまり ClickStack のデフォルトスキーマ が採用している構成により、新しいキーが増えても取り込み時の追加コストを発生させることなく、Map は読み取り時にも選択的かつ高速に動作します。
実際には、これは次のことを意味します。
- キーが増えても取り込みコストは安定。 新しい attribute キーを追加しても、ディスク上のカラムレイアウトは変わらず、新たな column file も作成されません。取り込みコストはキーのカーディナリティではなく、データ量によって決まります。
- メタデータの爆発的な増加を防げる。 ディスク上の column file の数は、一意な attribute キーの数に連動しません。
- 索引を使った選択的なルックアップ。 map のキーと値に対するテキスト索引により、すべての行をスキャンしなくても point lookup を実行できます。
- 高スループットでも予測可能な動作。
Mapは、tracing や logs で一般的な、バースト的でスキーマレスな attribute 群を、キーごとのオーバーヘッドなしで処理できます。
デフォルトで JSON を使わないのはなぜか
JSON 型は、これとは異なるアプローチを取ります。挿入時に、ClickHouse は見つかった各パスごとに、強く型付けされた専用のサブカラムを動的に作成します。読み取り時には、要求されたサブカラムだけを読み込めばよく、型も保持され、クエリ時のキャストも不要なため、これは魅力的です。
ただし、そのしわ寄せは取り込み時に生じます。多数の動的サブカラムを作成して管理すると、書き込み時のオーバーヘッドとメタデータの複雑さが増します。オブザーバビリティのワークロードでは、属性セットが非常に大きかったり変動が激しかったりするうえ、取り込みスループットも高いのが一般的なため、このオーバーヘッドは無視できません。max_dynamic_paths 制限を使えば、追加のパスを共有カラムに退避させることで影響を抑えられますが、共有カラムへのアクセスは専用サブカラムより遅いため、そもそも JSON を使う動機だった読み取り時の利点が薄れてしまいます。
bucketed map シリアライゼーションによって Map の従来の読み取り時オーバーヘッドの大半が解消されたため、一般的なオブザーバビリティのワークロードでは、JSON の読み取り時の利点は、もはや取り込み時のコストを上回りません。
それでも JSON を検討すべき場合
- 属性のキーセットが小さく安定しており、何千もの一意なキーが存在せず、新しいキーが追加されることもまれである。
- 取り込みスループットが、属性のカーディナリティに対して控えめである。
- クエリ時にキャストせず、属性に厳密な型でアクセスしたい (数値は数値のまま、ブール値はブール値のまま) 。
- ClickStack でベータ機能を運用し、インテグレーションが変更される可能性を受け入れられる。
Map ベースのスキーマを引き続き使用してください。
ベータステータス
2.0.4 から JSON 型をベータサポートしています。
JSON サポートの有効化
Mapベースのスキーマではなく JSON 型のスキーマを使用するには、以下の環境変数を設定します。
Managed ClickStack
OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' を設定します。例:
オープンソースの ClickStack
OTEL_AGENT_FEATURE_GATE_ARG='--feature-gates=clickhouse.json' を設定し、HyperDX のアプリケーションレイヤーでは BETA_CH_OTEL_JSON_SCHEMA_ENABLED=true を設定して、JSON 型のスキーマに対してクエリを実行できるようにします。
例:
MapベースのスキーマからJSONへの移行
1
OTel collector を停止する
2
3
OTel collector をデプロイする
OTEL_AGENT_FEATURE_GATE_ARG を設定して OTel collector をデプロイします。4
JSONスキーマ対応を有効にして HyperDX コンテナーを再起動する
5