有効期限 (TTL) は、継続的に大量のデータが生成される ClickStack において、データ保持と管理を効率化する重要な機能です。有効期限 (TTL) を使用すると、古いデータを自動的に期限切れとして削除できるため、手動で運用しなくてもストレージを最適に活用し、パフォーマンスを維持できます。これは、データベースを軽量に保ち、ストレージコストを削減し、最新かつ重要なデータに絞ってクエリを高速かつ効率的に実行するうえで不可欠です。さらに、データのライフサイクルを体系的に管理することで、データ保持ポリシーへの準拠にも役立ち、オブザーバビリティソリューション全体の持続可能性とスケーラビリティの向上にもつながります。
デフォルトでは、ClickStack はデータを 3 日間保持します。これを変更するには、“有効期限 (TTL) の変更” を参照してください。
有効期限 (TTL) は ClickHouse ではテーブルレベルで制御されます。たとえば、logs のスキーマは以下のとおりです。
CREATE TABLE default.otel_logs
(
`Timestamp` DateTime64(9) CODEC(Delta(8), ZSTD(1)),
`TimestampTime` DateTime DEFAULT toDateTime(Timestamp),
`TraceId` String CODEC(ZSTD(1)),
`SpanId` String CODEC(ZSTD(1)),
`TraceFlags` UInt8,
`SeverityText` LowCardinality(String) CODEC(ZSTD(1)),
`SeverityNumber` UInt8,
`ServiceName` LowCardinality(String) CODEC(ZSTD(1)),
`Body` String CODEC(ZSTD(1)),
`ResourceSchemaUrl` LowCardinality(String) CODEC(ZSTD(1)),
`ResourceAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
`ScopeSchemaUrl` LowCardinality(String) CODEC(ZSTD(1)),
`ScopeName` String CODEC(ZSTD(1)),
`ScopeVersion` LowCardinality(String) CODEC(ZSTD(1)),
`ScopeAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
`LogAttributes` Map(LowCardinality(String), String) CODEC(ZSTD(1)),
INDEX idx_trace_id TraceId TYPE bloom_filter(0.001) GRANULARITY 1,
INDEX idx_res_attr_key mapKeys(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
INDEX idx_res_attr_value mapValues(ResourceAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
INDEX idx_scope_attr_key mapKeys(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
INDEX idx_scope_attr_value mapValues(ScopeAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
INDEX idx_log_attr_key mapKeys(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
INDEX idx_log_attr_value mapValues(LogAttributes) TYPE bloom_filter(0.01) GRANULARITY 1,
INDEX idx_body Body TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 8
)
ENGINE = MergeTree
PARTITION BY toDate(TimestampTime)
PRIMARY KEY (ServiceName, TimestampTime)
ORDER BY (ServiceName, TimestampTime, Timestamp)
TTL TimestampTime + toIntervalDay(3)
SETTINGS ttl_only_drop_parts = 1
ClickHouse のパーティション化では、カラムまたは SQL 式に基づいて、データをディスク上で論理的に分離できます。データを論理的に分離することで、各パーティションを個別に操作できるようになります。たとえば、有効期限 (TTL) ポリシーに従って有効期限が切れた際に削除できます。
上記の例にあるように、パーティション化はテーブルの初期定義時に PARTITION BY 句で指定します。この句には任意のカラムに対する SQL 式を含めることができ、その結果によって、行がどのパーティションに送られるかが決まります。これにより、データはディスク上の各パーティションに対して論理的に関連付けられ (共通のフォルダー名のプレフィックスを介して) 、その後、個別にクエリできるようになります。上記の例では、デフォルトの otel_logs スキーマは、toDate(Timestamp). という式を使用して日単位でパーティション化されます。行が ClickHouse に挿入されると、この式が各行に対して評価され、該当するパーティションが存在すればそこに振り分けられます (その日の最初の行であれば、パーティションが作成されます) 。パーティション化とそのほかの用途の詳細については、“テーブルパーティション” を参照してください。
テーブルのスキーマには、TTL TimestampTime + toIntervalDay(3) と設定 ttl_only_drop_parts = 1 も含まれています。前者の句により、データは 3 日を超えると削除されます。設定 ttl_only_drop_parts = 1 は、行を部分的に削除しようとするのではなく、すべてのデータが期限切れになったデータパーツのみを削除するようにします。さらに、パーティション化によって別々の日のデータが決して「マージ」されないため、データを効率的に削除できます。
ttl_only_drop_parts設定 ttl_only_drop_parts=1 は常に使用することを推奨します。この設定を有効にすると、ClickHouse は、その中のすべての行が期限切れになった時点でパーツ全体を削除します。TTL で期限切れになった行を部分的にクリーンアップする代わりにパーツ全体を削除することで (ttl_only_drop_parts=0 の場合は、リソース負荷の高い mutation によって実行されます) 、merge_with_ttl_timeout を短く設定でき、システム性能への影響も抑えられます。TTL の期限切れを実行する単位 (たとえば日) と同じ単位でデータをパーティション化していれば、パーツには自然にその期間のデータだけが含まれるようになります。これにより、ttl_only_drop_parts=1 を効率的に適用できます。
デフォルトでは、有効期限 (TTL) が切れたデータは、ClickHouse がデータパーツをマージするときに削除されます。ClickHouse はデータの期限切れを検出すると、予定外のマージを実行します。
TTL スケジュール前述のとおり、TTL は即座には適用されず、スケジュールに従って適用されます。MergeTree テーブル設定 merge_with_ttl_timeout は、削除 TTL を伴うマージを再実行するまでの最小遅延時間 (秒) を設定します。デフォルト値は 14400 秒 (4 時間) です。ただし、これはあくまで最小遅延時間であり、TTL マージがトリガーされるまでにはさらに時間がかかる場合があります。値が低すぎると、リソースを大量に消費する予定外のマージが多数実行される可能性があります。TTL の期限切れは、コマンド ALTER TABLE my_table MATERIALIZE TTL を使って強制できます。
有効期限 (TTL) を変更するには、次のいずれかの方法を使用します。
- テーブルのスキーマを変更する (推奨) 。この方法では、たとえば clickhouse-client または Cloud SQL Console を使って ClickHouse インスタンスに接続する必要があります。たとえば、次の DDL を使用して
otel_logs テーブルの 有効期限 (TTL) を変更できます。
ALTER TABLE default.otel_logs
MODIFY TTL TimestampTime + toIntervalDay(7);
- OTel collectorを変更します。ClickStack OpenTelemetry collector は、ClickHouse にテーブルが存在しない場合、自動的に作成します。これは ClickHouse エクスポーターによって実現されており、このエクスポーターではデフォルトの 有効期限 (TTL) 式を制御するための
ttl パラメーターも公開されています。例:
exporters:
clickhouse:
endpoint: tcp://localhost:9000?dial_timeout=10s&compress=lz4&async_insert=1
ttl: 72h
上記の例では、テーブルレベルでデータを期限切れにしています。カラムレベルでデータを期限切れにすることもできます。データの経過に応じて、調査での利用価値が保持に伴うリソースのオーバーヘッドに見合わないカラムを削除する目的で、これを利用できます。たとえば、insert time にまだ抽出されていない新しい動的メタデータが追加される可能性に備えて、Body カラムは保持しておくことを推奨します。たとえば、新しい Kubernetes ラベルなどです。一定期間、たとえば 1 か月が経過すると、この追加メタデータが有用でないことが明らかになる場合があり、その場合 Body カラムを保持する価値は低くなります。
以下では、Body カラムを 30 日後に削除する方法を示します。
CREATE TABLE otel_logs_v2
(
`Body` String TTL Timestamp + INTERVAL 30 DAY,
`Timestamp` DateTime,
...
)
ENGINE = MergeTree
ORDER BY (ServiceName, Timestamp)
カラムレベルの有効期限 (TTL) を指定するには、独自のスキーマを定義する必要があります。これは OTel collector では指定できません。