Перейти к основному содержанию

TTL в ClickStack

Time-to-Live (TTL) — важная возможность ClickStack для эффективного хранения и управления данными, особенно с учетом того, что постоянно генерируются огромные объемы данных. TTL позволяет автоматически удалять старые данные по истечении срока хранения, обеспечивая оптимальное использование хранилища и поддерживая производительность без ручного вмешательства. Эта возможность необходима для того, чтобы база данных оставалась компактной, снижались затраты на хранение, а запросы выполнялись быстро и эффективно за счет работы только с наиболее актуальными и свежими данными. Кроме того, TTL помогает соблюдать политики хранения данных благодаря систематическому управлению их жизненным циклом, повышая тем самым общую устойчивость и масштабируемость решения для обсервабилити. По умолчанию ClickStack хранит данные 3 дня. Чтобы изменить этот параметр, см. “Изменение TTL”. В ClickHouse TTL настраивается на уровне таблицы. Например, ниже показана схема журналов:
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) позволяет использовать меньшие значения merge_with_ttl_timeout и снижает нагрузку на систему. Если данные разбиты на партиции по той же единице, по которой выполняется истечение TTL, например по дням, части естественным образом будут содержать данные только из заданного интервала. Это обеспечивает эффективное применение ttl_only_drop_parts=1.
По умолчанию данные с истекшим TTL удаляются, когда ClickHouse выполняет слияние частей данных. Когда ClickHouse обнаруживает, что срок хранения данных истек, он выполняет внеплановое слияние.
Расписание TTLTTL применяются не сразу, а по расписанию, как отмечалось выше. Настройка таблицы MergeTree merge_with_ttl_timeout задает минимальную задержку в секундах перед повторным выполнением слияния с delete TTL. Значение по умолчанию — 14400 секунд (4 часа). Но это лишь минимальная задержка; до запуска TTL-слияния может пройти больше времени. Если значение слишком низкое, будет выполняться много внеплановых слияний, которые могут потреблять много ресурсов. Принудительно применить TTL можно командой ALTER TABLE my_table MATERIALIZE TTL.

Изменение TTL

Чтобы изменить TTL, можно сделать одно из следующего:
  1. Изменить схемы таблиц (рекомендуется). Для этого нужно подключиться к экземпляру ClickHouse, например с помощью clickhouse-client или Cloud SQL Console. Например, TTL таблицы otel_logs можно изменить с помощью следующего DDL:
ALTER TABLE default.otel_logs
MODIFY TTL TimestampTime + toIntervalDay(7);
  1. Измените OTel collector. Коллектор ClickStack OpenTelemetry создает таблицы в ClickHouse, если они отсутствуют. Это достигается с помощью экспортера ClickHouse, который, в свою очередь, предоставляет параметр ttl, позволяющий задавать выражение TTL по умолчанию, например.
exporters:
 clickhouse:
   endpoint: tcp://localhost:9000?dial_timeout=10s&compress=lz4&async_insert=1
   ttl: 72h

TTL на уровне столбца

В приведенных выше примерах срок хранения данных задается на уровне таблицы. Вы также можете задавать срок хранения данных на уровне столбца. По мере устаревания данных это можно использовать для удаления столбцов, ценность которых при расследовании инцидентов не оправдывает затраты ресурсов на их хранение. Например, мы рекомендуем сохранять столбец 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.
Последнее изменение 10 июня 2026 г.