Итоги модуля: Data Modeling Patterns
Модуль 07 покрывает шесть фундаментальных паттернов моделирования данных в ClickHouse. Каждый паттерн решает конкретный класс задач: от аналитики событий до управления dimension-таблицами.
Этот урок связывает все шесть паттернов в единую систему принятия решений.
Краткий обзор паттернов
Урок 1: Денормализация и широкие таблицы (OBT)
Главный принцип: JOIN при INSERT, а не при SELECT. В ClickHouse JOIN загружает правую таблицу целиком в RAM, поэтому денормализация (One Big Table) устраняет JOINs из аналитических запросов. ETL pipeline обогащает факты dimension-данными при записи. Компромисс — dictGet() для dimension enrichment без полной денормализации. Не подходит для часто обновляемых dimensions (high churn).
Урок 2: Моделирование временных рядов
Ключевые решения: кодеки и ORDER BY. Codec chains: Delta+ZSTD для timestamps, Gorilla+LZ4 для float-значений, DoubleDelta+ZSTD для монотонных счётчиков. ORDER BY (metric_name, timestamp) — metric first для cardinalitу ordering, timestamp second для range-сканов. DateTime64(3) для миллисекундной гранулярности. PARTITION BY toYYYYMM() для lifecycle management через TTL.
Урок 3: Схемы для лог-аналитики
ClickHouse как замена ELK/Loki: столбцовое хранение + text index + TTL. LowCardinality для уровней и сервисов, text index (GA 26.2) для полнотекстового поиска по message, bloom_filter для trace_id корреляции, Map(LowCardinality(String), String) для переменных атрибутов (Kubernetes labels). Daily partitions + TTL для агрессивного retention. 5-10x экономия места по сравнению с Elasticsearch.
Урок 4: Медленно меняющиеся измерения (SCD)
ReplacingMergeTree для SCD Type 1 (overwrite): version column + FINAL при чтении. SCD Type 2 (full history) через plain MergeTree с valid_from/valid_to. is_deleted для soft-delete в ReplacingMergeTree (24.x+). Критическая деталь: дедупликация происходит при merge, а не при INSERT — между merges видны все версии.
Урок 5: Nested, Map и плоские схемы для событий
Четыре подхода к хранению event properties: Nested (параллельные массивы, ARRAY JOIN для разворачивания), плоская схема (фиксированные столбцы, максимальная производительность запросов), Map (переменные ключи, динамические атрибуты), JSON type (GA 25.3, полностью semi-structured). Nested — для известных ключей с умеренной кардинальностью. Плоская — для фиксированной схемы. Map — для переменных атрибутов. JSON — для полностью динамических данных.
Урок 6: Стратегии дедупликации
Четыре стратегии: ReplacingMergeTree + FINAL (простейший паттерн, дедупликация при чтении), argMax/argMin (query-time dedup через GROUP BY, без зависимости от merge state), Deduplicated MV (AggregatingMergeTree + argMaxState, insert-time dedup, лучшая производительность чтения), OPTIMIZE TABLE FINAL (batch cleanup, O(all data), только для maintenance).
Decision framework: какой паттерн выбрать?
Матрица выбора паттерна
| Ваши данные | Рекомендуемый паттерн | Ключевой механизм |
|---|---|---|
| Факты + dimensions, аналитические запросы | Денормализация (OBT) | ETL JOIN при INSERT, dictGet() для dimension enrichment |
| Числовые значения с timestamps | Временные ряды | Delta/Gorilla кодеки, ORDER BY (metric, ts) |
| Текстовые логи, traces | Лог-аналитика | text index, bloom_filter, Map, TTL |
| Справочники с редкими обновлениями | SCD | ReplacingMergeTree + FINAL или MergeTree + valid_from/valid_to |
| События со свойствами | Nested / Map / Flat | Зависит от динамичности схемы |
| Потоки с дубликатами (CDC, Kafka) | Дедупликация | ReplacingMergeTree, argMax, MV, OPTIMIZE |
Связь с другими модулями
Паттерны модуля 07 опираются на механизмы, изученные ранее:
- Модуль 01 (Storage Engine): parts, merges, кодеки — фундамент для всех паттернов. Codec chains из Урока 2 работают благодаря per-column compression в MergeTree parts.
- Модуль 03 (Engine Family): ReplacingMergeTree, SummingMergeTree, AggregatingMergeTree — движки для SCD и дедупликации. Выбор движка определяет паттерн.
- Модуль 04 (Materialized Views): MV + AggregatingMergeTree — основа для Deduplicated MV (стратегия 3 из Урока 6). Также MV для pre-aggregation в time-series.
- Модуль 05 (Skip Indexes): text index для лог-аналитики, bloom_filter для trace correlation — механизмы индексации из Модуля 05 применяются в паттернах Модуля 07.
Ключевые выводы
-
Денормализация — основной паттерн для аналитики в ClickHouse. JOIN при INSERT через ETL, а не при каждом SELECT. dictGet() — компромисс для часто обновляемых dimensions.
-
Codec chains определяют эффективность time-series: Delta+ZSTD для timestamps, Gorilla+LZ4 для float. ORDER BY (metric, ts) — metric first для cardinality ordering.
-
text index (GA 26.2) заменяет ngrambf_v1/tokenbf_v1 для полнотекстового поиска в логах. Map — для переменных атрибутов. Daily partitions + TTL для retention.
-
ReplacingMergeTree — инструмент для SCD Type 1. Дедупликация при merge, а не при INSERT. FINAL для чтения актуальной версии. is_deleted для soft-delete.
-
Выбор формата event properties зависит от динамичности схемы: Flat (максимум производительности), Nested (известные ключи), Map (переменные), JSON (динамические).
-
Четыре стратегии дедупликации покрывают весь спектр: от простого FINAL до MV с argMaxState. OPTIMIZE TABLE FINAL — только для batch maintenance, никогда в application code.