Storage Policy и MOVE TTL
Многоуровневая стратегия хранения (tiered storage) позволяет хранить горячие данные на быстром локальном диске, а холодные — дешёвом объектном хранилище, например S3. ClickHouse управляет перемещением данных между уровнями автоматически через MOVE TTL и storage policy, без ручных скриптов.
Архитектура: диски, volumes и политики
Tiered storage строится из трёх концепций:
- Диск (disk) — физическое или логическое хранилище: локальный путь, S3-бакет, кеш поверх S3.
- Volume — группа дисков одного уровня (hot, warm, cold).
- Storage policy — набор volumes с правилами заполнения.
Конфигурация storage.xml
Storage policy задаётся в XML-конфигурации ClickHouse. В лабораторной среде с MinIO:
<!-- /etc/clickhouse-server/config.d/storage.xml -->
<clickhouse>
<storage_configuration>
<disks>
<!-- Встроенный локальный диск (default) объявлять не нужно -->
<s3_cold>
<type>s3</type>
<endpoint>http://minio:9000/clickhouse-cold/</endpoint>
<access_key_id>minioadmin</access_key_id>
<secret_access_key>minioadmin123</secret_access_key>
<use_path_style_url>1</use_path_style_url>
<metadata_path>/var/lib/clickhouse/disks/s3_cold/</metadata_path>
</s3_cold>
<s3_cache>
<type>cache</type>
<disk>s3_cold</disk>
<path>/var/lib/clickhouse/disks/s3_cache/</path>
<max_size>2Gi</max_size>
</s3_cache>
</disks>
<policies>
<tiered>
<volumes>
<hot>
<disk>default</disk>
</hot>
<cold>
<disk>s3_cold</disk>
</cold>
</volumes>
</tiered>
</policies>
</storage_configuration>
</clickhouse>
Параметр use_path_style_url обязателен для MinIO и других S3-совместимых хранилищ. Без него ClickHouse использует virtual-hosted style (bucket.hostname), что не поддерживается большинством self-hosted S3 реализаций. Для AWS S3 этот параметр не нужен.
MOVE TTL: синтаксис и примеры
MOVE TTL добавляется к обычному TTL-выражению с указанием целевого volume или диска:
-- Таблица с hot/cold tiered storage
CREATE TABLE events_tiered
(
event_time DateTime,
user_id UInt64,
payload String
)
ENGINE = MergeTree
ORDER BY (user_id, event_time)
PARTITION BY toYYYYMM(event_time)
SETTINGS storage_policy = 'tiered'
TTL event_time + INTERVAL 30 DAY TO VOLUME 'cold';
-- Альтернатива: несколько TTL-правил (hot → warm → delete)
CREATE TABLE events_multi_ttl
(
event_time DateTime,
user_id UInt64,
payload String
)
ENGINE = MergeTree
ORDER BY (user_id, event_time)
PARTITION BY toYYYYMM(event_time)
SETTINGS storage_policy = 'tiered'
TTL
event_time + INTERVAL 30 DAY TO VOLUME 'cold', -- переместить на холодный уровень
event_time + INTERVAL 365 DAY DELETE; -- удалить совсем через год
MOVE TTL перемещает целые parts, а не отдельные строки. Если part содержит строки с разными event_time (часть истёкших, часть нет), part не перемещается до тех пор, пока все строки в нём не пройдут TTL. Это означает, что разбиение по партициям (PARTITION BY toYYYYMM) критично для эффективного tiered storage: данные одного месяца оказываются в одном part.
JBOD: несколько дисков в одном volume
JBOD (Just a Bunch Of Disks) — паттерн, при котором несколько физических дисков объединяются в один volume. ClickHouse распределяет новые parts между дисками по round-robin.
<policies>
<jbod_policy>
<volumes>
<hot>
<disk>disk1</disk>
<disk>disk2</disk>
<disk>disk3</disk>
<!-- Parts распределяются равномерно; при заполнении одного диска запись продолжается на других -->
</hot>
</volumes>
</jbod_policy>
</policies>
JBOD не даёт отказоустойчивости (это не RAID): при потере одного диска данные на нём теряются. Но JBOD масштабирует ёмкость без изменения логики таблиц.
s3_cache: кеш поверх S3
s3_cache — специальный тип диска, который прозрачно кеширует recently-accessed parts с S3 на локальный диск. Это ускоряет повторные чтения с холодного уровня без изменения SQL-запросов.
-- Использование s3_cache вместо s3_cold в политике (прозрачно для запросов)
CREATE TABLE events_cached
(
event_time DateTime,
payload String
)
ENGINE = MergeTree
ORDER BY event_time
SETTINGS storage_policy = 'tiered_with_cache' -- cold volume использует s3_cache
TTL event_time + INTERVAL 30 DAY TO VOLUME 'cold';
Практический сценарий: горячий журнал событий
-- Полный пример: горячий журнал с автоматическим перемещением на S3 через 30 дней
-- и полным удалением через 1 год
CREATE TABLE access_log
(
event_time DateTime DEFAULT now(),
user_id UInt64,
action LowCardinality(String),
resource String,
ip_address String TTL event_time + INTERVAL 30 DAY -- IP обнуляется раньше строки
)
ENGINE = MergeTree
ORDER BY (user_id, event_time)
PARTITION BY toYYYYMM(event_time)
SETTINGS storage_policy = 'tiered'
TTL
event_time + INTERVAL 30 DAY TO VOLUME 'cold',
event_time + INTERVAL 365 DAY DELETE;
-- Проверить текущие диски через system.disks
SELECT name, path, type, free_space, total_space
FROM system.disks;
-- Проверить storage policy
SELECT policy_name, volume_name, disk_name, max_data_part_size
FROM system.storage_policies
WHERE policy_name = 'tiered';
Для практики с MinIO и реальным MOVE TTL выполните лабораторную работу labs/minio/. Там настроена полная конфигурация с cgr.dev/chainguard/minio и ClickHouse 26.3 LTS.
Ключевые выводы
- Storage policy состоит из дисков (disk) → volumes → политики; таблица указывает политику через
SETTINGS storage_policy = 'name'. - MOVE TTL перемещает целые parts между volumes — не отдельные строки. Партиционирование по времени критично для эффективного MOVE.
- JBOD объединяет несколько дисков в один volume с round-robin распределением — масштабирует ёмкость, но не даёт отказоустойчивости.
s3_cache— прозрачный кеш поверх S3-диска, ускоряет повторные чтения без изменения SQL.use_path_style_url=1обязателен для MinIO и других self-hosted S3 реализаций.