Управление сроком жизни данных (TTL, time to live)
Обзор TTL
TTL (time-to-live) — это механизм, позволяющий перемещать, удалять или агрегировать строки или столбцы по истечении определённого интервала времени. Хотя выражение «time-to-live» звучит так, будто оно относится только к удалению старых данных, у TTL есть несколько сценариев использования:
- Удаление старых данных: как и ожидается, вы можете удалять строки или столбцы по истечении заданного временного интервала
- Перемещение данных между дисками: по прошествии определённого времени вы можете перемещать данные между томами хранилища — это полезно для реализации архитектуры горячего/тёплого/холодного хранения
- Свёртка данных (rollup): выполняйте свёртку старых данных в различные полезные агрегаты и вычисления перед их удалением
TTL может применяться ко всей таблице или к отдельным столбцам.
Синтаксис TTL
Предложение TTL может располагаться после определения столбца и/или в конце определения таблицы. Используйте предложение INTERVAL, чтобы задать продолжительность интервала (значение должно иметь тип данных Date или DateTime). Например, в следующей таблице есть два столбца
с предложениями TTL:
- Столбец x имеет время жизни 1 месяц, отсчитываемый от значения в столбце timestamp
- Столбец y имеет время жизни 1 день, отсчитываемый от значения в столбце timestamp
- По истечении этого интервала срок жизни столбца истекает. ClickHouse заменяет значение столбца значением по умолчанию для его типа данных. Если срок жизни всех значений столбца в части данных истёк, ClickHouse удаляет этот столбец из части данных в файловой системе.
Правила TTL можно изменить или удалить. Дополнительные сведения см. на странице Manipulations with Table TTL.
Запуск событий TTL
Удаление или агрегирование просроченных строк происходит не сразу — оно выполняется только во время слияний таблицы. Если у вас есть таблица, для которой по какой-либо причине не выполняются слияния, существуют два параметра, которые запускают события TTL:
merge_with_ttl_timeout: минимальная задержка в секундах перед повторным выполнением слияния с TTL на удаление. Значение по умолчанию — 14400 секунд (4 часа).merge_with_recompression_ttl_timeout: минимальная задержка в секундах перед повторным выполнением слияния с TTL на перекомпрессию (правила, которые сворачивают данные перед удалением). Значение по умолчанию — 14400 секунд (4 часа).
Таким образом, по умолчанию ваши правила TTL будут применяться к вашей таблице как минимум раз в 4 часа. Измените параметры выше, если вам нужно, чтобы правила TTL применялись чаще.
Не самое лучшее решение (и не то, которое мы рекомендуем использовать часто), но вы также можете принудительно запустить слияние с помощью OPTIMIZE:
OPTIMIZE запускает внеплановое слияние частей вашей таблицы, а FINAL принудительно выполняет повторную оптимизацию, даже если таблица уже состоит из одной части.`
Удаление строк
Чтобы удалять целые строки из таблицы по истечении определённого времени, задайте правило TTL на уровне таблицы:
Кроме того, можно определить правило TTL, основанное на значении записи. Это легко сделать, указав условие WHERE. Допускается использование нескольких условий:
Удаление столбцов
Вместо удаления всей строки предположим, что вы хотите задать срок действия только для столбцов balance и address. Давайте изменим таблицу customers и добавим для обоих столбцов TTL в 2 часа:
Реализация rollup-агрегирования
Предположим, мы хотим удалять строки по истечении определённого времени, но при этом сохранять часть данных для отчётности. Нам не нужны все детали — только несколько агрегированных результатов по историческим данным. Это можно реализовать, добавив предложение GROUP BY к выражению TTL, а также несколько столбцов в таблицу для хранения агрегированных результатов.
Предположим, что в следующей таблице hits мы хотим удалять старые строки, но при этом сохранять сумму и максимум по столбцам hits перед удалением строк. Нам понадобится поле для хранения этих значений, и нам нужно будет добавить предложение GROUP BY в выражение TTL, которое будет агрегировать сумму и максимум:
Некоторые замечания по таблице hits:
- Столбцы
GROUP BYв предложенииTTLдолжны представлять собой префиксPRIMARY KEY, а нам нужно группировать результаты по началу дня. ПоэтомуtoStartOfDay(timestamp)был добавлен в первичный ключ - Мы добавили два поля для хранения агрегированных результатов:
max_hitsиsum_hits - Задание значения по умолчанию для
max_hitsиsum_hits, равногоhits, необходимо для корректной работы нашей логики, исходя из того, как определено предложениеSET
Реализация архитектуры «hot/warm/cold»
Если вы используете ClickHouse Cloud, шаги из этого урока неприменимы. Вам не нужно беспокоиться о переносе старых данных в ClickHouse Cloud.
Распространённая практика при работе с большими объёмами данных — перемещать эти данные по мере их устаревания. Ниже приведены шаги по реализации архитектуры «hot/warm/cold» в ClickHouse с использованием опций TO DISK и TO VOLUME команды TTL. (Кстати, это не обязательно должна быть схема только hot и cold — вы можете использовать TTL для перемещения данных между любыми уровнями в соответствии с вашим сценарием.)
- Опции
TO DISKиTO VOLUMEссылаются на имена дисков или томов, определённых в ваших конфигурационных файлах ClickHouse. Создайте новый файл с именемmy_system.xml(или любым другим именем файла), в котором будут определены ваши диски, затем определите тома, использующие эти диски. Поместите XML-файл в/etc/clickhouse-server/config.d/, чтобы конфигурация была применена к вашей системе:
- В приведённой выше конфигурации используются три диска, которые ссылаются на каталоги, из которых ClickHouse может читать и в которые может записывать. Том может содержать один или несколько дисков — мы определили отдельный том для каждого из трёх дисков. Давайте посмотрим на диски:
- Теперь проверим тома:
- Теперь мы добавим правило
TTL, которое перемещает данные между горячим, тёплым и холодным томами:
- Новое правило
TTLдолжно материализоваться автоматически, но при необходимости вы можете принудительно выполнить его материализацию, чтобы убедиться:
- Проверьте, что ваши данные переместились на нужные диски, используя таблицу
system.parts:
Ответ будет выглядеть следующим образом: