BI Consult Desktop Logo BI Consult Mobile Logo
  • Russian BI Исследование российских bi
  • Перейти на Fine BI
  • Контакты
  • +7 812 334-08-01
    +7 499 608-13-06
  • Отправить сообщение
  • Главная
  • Продукты Эксперт-BI
    • Дистрибуция
    • Розничная торговля
    • Производство
    • Операторы связи
    • Страхование
    • Банки
    • Лизинг
    • Логистика
    • Нефтегазовый сектор
    • Медицина
    • Сеть ресторанов
    • E-Commerce
    • Сельское хозяйство
    • Энергетика
    • FMCG
    • Девелоперы
    • Маркетплейсы
    • Пищевая промышленность
    • Фармацевтика
    • Построение Data Platform
    • Цифровая трансформация
    • Управление по KPI
    • Финансы
    • Продажи
    • Склад
    • HR
    • Маркетинг
    • Внутренний аудит
    • Категорийный менеджмент
    • S&OP и FP&A
    • Геоаналитика
    • Цепочки поставок (SCM)
    • AutoML
    • Process Mining
    • IBP
    • ИТ (CIO)
    • Закупки
  • Платформы
    • Системы бизнес-анализа (BI)
    • Интегрированное бизнес-планирование (IBP)
    • Хранилища данных (DWH / Lakehouse)
    • Каталоги данных (Data Catalog)
    • Системы ETL и ELT
    • AI / Исскуственный интеллект
    • Шина данных (ESB)
    • Система управления мастер-данными (MDM)
    • Семантический слой
  • Услуги
    • Переход на отечественные BI и DWH системы
    • Консалтинг
    • Пилотный проект
    • Обучение и сертификация
    • Бесплатное обучение
    • Поддержка
    • Технические задания
    • Сбор требований для проекта внедрения BI-системы
    • CI/CD для DWH
    • Аудит BI приложений и DWH
    • Выделенная команда
    • Настойка и поддержка баз данных
    • Разработка BI Стратегии
    • Styleguide для BI-системы
    • Как выбрать BI-систему
  • Курсы
    • Учебный курс Информационная грамотность (Data Literacy)
    • Учебный курс для бизнес-аналитиков
    • Учебный курс для системных аналитиков
    • Учебный курс по Data Governance
    • Учебный курс Как стать CDO
    • Учебный курс Современная архитектура хранилища данных
    • Учебный курс по Fine BI
    • Учебный курс по FineReport
    • Учебный курс по DWH
    • Учебный курс по Data Science (ML, AI)
    • Учебный курс по PostgreSQL
    • Учебный курс по Greenplum
    • Учебный курс по Apache Airflow и NiFi
    • Учебный курс по Open-source BI
    • Учебный курс по ClickHouse
    • Учебный курс по DataLens
    • Учебный курс по Loginom
    • Учебный курс по Modus BI и ETL
    • Учебный курс по Visiology
    • Учебный курс по dbt (Data Build Tool)
  • Компания
    • Руководство
    • Новости
    • Клиенты
    • Карьера
    • Скачать
    • Контакты

BI

  • FineBI
  • FineReport
  • FineDataLink
  • FineChatBI (FineAI)
  • Коннекторы данных из 1С в BI
  • Airflow / Nifi
  • Visiology
  • PIX BI
  • Modus BI
  • Yandex.DataLens
  • Open-source BI: Superset/Metabase
  • Luxms BI
  • AW BI + Alpha BI
  • FlyBI + Форсайт. Аналитическая Платформа
  • Loginom
  • Триафлай
  • AI / Исскуственный интеллект
  • Optimacros
  • Навигатор BI
  • Семантический слой

СУБД

  • Arenadata
  • ClickHouse
  • Greenplum
  • Postgres Professional
  • TData

Другое

  • Построение Data Platform
    • Аналитическое хранилище данных
    • Data Lake и Data Engineering
    • Подробнее про Data Lake
    • Внедрение Lakehouse
      • Apache Doris
      • StarRocks
      • Trino
    • Миграция витрин из пропиетарных DWH на новый стек
    • Учебный курс "Современная архитектура хранилища данных"
Главная » Курсы по системам бизнес-анализа и методологии » Учебный курс по ClickHouse » Курс «Витрины данных на ClickHouse: от архитектуры до SLA» » Модуль 2. Моделирование витрин под ClickHouse

Модуль 2. Моделирование витрин под ClickHouse

(wide vs star, зерно и ключи, SCD0/1/2, pre-join, инкременты/CDC, агрегаты, ORDER BY/партиции, миграции, кейсы)

 

Куда «ложится» моделирование витрин

Слой витрин (MARTS) — интерфейс между «правдой» (CORE) и потребителями (BI, аналитики, сервисы). Моделирование отвечает на 6 вопросов:

  1. Зерно (grain): какая одна строка — какой факт/срез?
  2. Срезы/измерения: какие атрибуты нужны и где они жить будут?
  3. Материализация: что посчитать заранее (агрегаты, состояния)?
  4. Инкременты: как довозить изменения без полного пересчёта?
  5. Физика ClickHouse: партиции, ORDER BY, движок (MergeTree-семейство), индексы.
  6. Жизненный цикл: миграции v1→v2 без простоя, тесты, регламенты.

 

Зерно витрины: ставим «точку опоры»

Правило: сначала зерно, потом всё остальное. Типичные зерна:

  • Транзакционное: чек-позиция, платеж, событие.
  • Снапшот: «состояние на конец дня/часа» (остатки, активные подписки).
  • Агрегат: день × магазин × категория (предрассчитанный слой).

 

Чек-лист выбора зерна

  • Какой вопрос отвечает витрина? («сколько продали по дням × магазинам»)
  • Какая минимальная дробность нужна BI? (день/час/мин)
  • Какие фильтры будут стоять в 90% запросов? (дата → магазин → категория)
  • Как будете обновлять (инкремент/ретро)?
  • Какая цена ошибки дубля? (для платежей — критично)

 

Риск: «размытое зерно» (в строке и факт, и агрегат) → путаница и дубли.
Митигация: отдельно витрина фактов и отдельно агрегаты.

 

Модель: wide vs star vs гибрид

Wide (широкая, денормализованная)

Одна строка содержит факт и нужные атрибуты измерений «на дату среза».

Когда: отчёты с простыми разрезами, высокая нагрузка чтения, нежелательны JOIN на лету.
Плюсы: быстро, стабильно, мало соединений.
Минусы: дубли атрибутов, обновления атрибутов сложнее (SCD-логика).

Пример:

CREATE TABLE mart_sales_wide
(
  tx_datetime DateTime,
  day Date MATERIALIZED toDate(tx_datetime),
  shop_id UInt32, shop_name LowCardinality(String), region_id UInt16,
  sku_id UInt32, sku_name String, brand LowCardinality(String), category_id UInt32,
  qty Int32, amount Decimal(12,2), currency FixedString(3),
  status_canon LowCardinality(String),
  customer_id UInt64
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(day)
ORDER BY (day, shop_id, sku_id);

 

Star (звезда)

Факты отдельно, измерения отдельно (d_shop, d_sku…), связь по ключам.

Когда: много сочетаний измерений, нужна гибкость, частые изменения справочников.
Плюсы: меньше дублирования, независимая эволюция измерений.
Минусы: JOIN дороже; надо проектировать ключи и ORDER BY под запросы.

Компромисс (часто лучший вариант): хранить в факте ключи измерений + несколько «часто используемых» атрибутов, а редкие/тяжёлые атрибуты подтягивать pre-join в агрегатах или в отдельные тематические wide-витрины.

 

SCD для измерений в ClickHouse

Типы SCD

  • SCD0: «заморозили» значение — не меняется.
  • SCD1: «переписали» на новое (историю не храним).
  • SCD2: ведём версии (period from/to, current_flag) — «каким было на дату X».

 

Где вести SCD

  • В идеале — в CORE, а в MARTS уже «снимки» на дату факта.
  • Если SCD нужно вести прямо в MARTS: используем ReplacingMergeTree(version) для версий или «периодизацию» (from/to) в измерении.

 

SCD2-измерение (упрощённо):

CREATE TABLE d_shop_scd2
(
  shop_id UInt32,
  shop_name String,
  region_id UInt16,
  valid_from DateTime,
  valid_to   DateTime,
  is_current UInt8
)
ENGINE = MergeTree
ORDER BY (shop_id, valid_from);

 

Присоединение «на дату транзакции»:

SELECT f.*, d.shop_name, d.region_id
FROM f_sales f
JOIN d_shop_scd2 d
  ON d.shop_id = f.shop_id
 AND f.tx_datetime >= d.valid_from
 AND f.tx_datetime <  d.valid_to

 

Для скорости — материализуем snapshot атрибутов в широкую витрину при загрузке.

Риск: JOIN по интервалу без индекса может быть тяжелым.
Митигация: pre-join в процессе ETL и записать результат; либо хранить ежедневные snapshot-версии ключевых атрибутов.

 

Ключи и уникальность

Бизнес-ключи vs суррогатные

  • Бизнес-ключ (order_id, (shop_id, receipt_no)) — понятен домену, но может меняться/пересекаться.
  • Суррогат (UInt64/UUID) — удобен для дедупа/распределения.

 

Рекомендация: хранить оба: суррогат для техпроцессов, бизнес-ключ — для аудит-следа.

 

Уникальность

В ClickHouse жёсткой уникальности нет — вы её обеспечиваете дисциплиной записи и периодическими проверками.
Для идемпотентности: ReplacingMergeTree(version) или предварительный дедуп на STAGE.

Риск: тихие дубли «накручивают» суммы в Summing-агрегатах.
Митигация:

  • тест «дубликатов зерна» по окну;
  • для сумм — использовать AggregatingMergeTree (состояния), устойчивые к повторной заливке.

 

Инкременты, «поздние» события и ретро-пересчёты

Инкрементальные паттерны

  • Append-only: «вставили и забыли» (события).
  • Upsert: пришла новая версия записи → заменить старую (Replacing).
  • Сигналы +/-: вставка/удаление (Collapsing/VersionedCollapsing).
  • Агрегат-состояния: …State/…Merge (Aggregating).

 

Поздние события / ретро-окно

Фиксируем окно late events — напр., «14 дней дозаливаем». В джобах:

  • инкремент: «каждые 15 минут за последние 2 часа»;
  • ночной ретро-пересчёт: «за 30 дней».

 

Риск: бесконечный полнопересчёт.
Митигация: side-by-side пересборка (v2-таблица) и переключение; оконные ретро-пересчёты, а не «вся история».

 

Материализация: pre-join и pre-aggregate

Pre-join

Дорогие/частые JOIN делаем заранее (в широкую витрину или агрегат). Особенно — SCD-атрибуты «на дату факта», статусы, валюты.

 

Pre-aggregate

Частые группировки (день×магазин×категория, минута×канал) считаем и храним. Выбор движка:

  • SummingMergeTree — если не будет переигровок (повторных заливок).
  • AggregatingMergeTree — устойчивые состояния (sumState, uniq*State, quantile*State) → на чтении …Merge.
  • Projections — только после профилирования, точечно.

 

Риск: Summing + повторная заливка = удвоение.
Митигация: Aggregating (состояния) или пересборка целевого окна из «чистого» источника.

 

Физика ClickHouse: партиционирование, ORDER BY, индексы

Партиционирование

  • По времени: toYYYYMM(day) / toYYYYMMDD(day) (месяц/день).
  • Выбор: события с высоким трафиком — дневные; продажи — месячные.
  • Слишком мелко → part explosion. Слишком крупно → неудобный ретро-пересчёт.

 

ORDER BY (префикс PRIMARY KEY)

ORDER BY — главный рычаг. Он определяет физический порядок в частях. Делайте под типовые фильтры: дата → разрез → идентификатор.

 

Примеры:

  • Продажи: (day, shop_id, sku_id)
  • События: (event_time, user_id[, session_id])
  • Балансы: (day, account_id)

 

Индексы-скипы

  • minmax по числам/датам;
  • bloom_filter для LIKE/IN больших списков;
  • set для маленьких доменов.

Риск: длинный ORDER BY по высококардинальным полям → рост метаданных, слабый эффект.
Митигация: держите префикс коротким и соответствующим фильтрам.

 

Дедупликация и идемпотентность

ReplacingMergeTree(version)

Хранит все версии; при merge остаётся запись с максимальной version.

Паттерн:

  • источник даёт монотонную version (ts/event_id_seq);
  • на чтении не использовать FINAL в BI → дисциплина upstream (не плодить версии) + чтение «закрытых» партиций.

 

Collapsing/VersionedCollapsing

Подходит для логов +/-, где удаление моделируется отдельной записью со знаком. Требует строгой дисциплины порядка.

 

Дедуп на STAGE

Лучше всего — дедуп перед записью в витрину (по ключу+версии), а Replacing — как страховка.

Риск: привыкание к FINAL для консистентности.
Митигация: архитектурно обеспечить уникальность в окне → BI без FINAL.

 

Моделирование измерений: справочники, словари, маппинги

  • d_calendar: календарь (григорианский и/или 4-5-4), единый для всех.
  • d_status_map: маппинг статусов источников → канонические (PAID, REFUND…).
  • dict_fx: курсы валют (на дату).
  • d_uom / dict_uom: единицы измерения и коэффициенты.

 

Риск: «UNKNOWN» статусы «портят» цифры.
Митигация: алерт «новые статусы», ежедневный разбор, строгий контракт «откуда берём истину».

 

Типовые шаблоны таблиц (копируй и адаптируй)

Факт продаж (wide)

CREATE TABLE mart_sales_wide
(
  tx_id UInt64,
  tx_datetime DateTime,
  day Date MATERIALIZED toDate(tx_datetime),
  shop_id UInt32, shop_name LowCardinality(String), region_id UInt16,
  sku_id UInt32, category_id UInt32, brand LowCardinality(String),
  qty Int32, amount Decimal(12,2), currency FixedString(3),
  status_canon LowCardinality(String),
  customer_id UInt64
)
ENGINE = MergeTree
PARTITION BY toYYYYMM(day)
ORDER BY (day, shop_id, sku_id, tx_id);

 

Агрегат «день × магазин × категория» (устойчивый)

CREATE TABLE agg_sales_daily_state
(
  day Date, shop_id UInt32, category_id UInt32,
  amount_state AggregateFunction(sum, Decimal(14,2)),
  qty_state    AggregateFunction(sum, Int64)
)
ENGINE = AggregatingMergeTree
PARTITION BY toYYYYMM(day)
ORDER BY (day, shop_id, category_id);

 

Справочник статусов

CREATE TABLE d_status_map
(
  src_system LowCardinality(String),
  src_status LowCardinality(String),
  canonical_status LowCardinality(String)
)
ENGINE = MergeTree
ORDER BY (src_system, src_status);

 

Миграции схем и эволюция витрин

Additive-изменения

ADD COLUMN — безопасно; DROP/RENAME — через v2-таблицу.

 

Side-by-side (v1→v2)

  • создаём *_v2 (новое ORDER BY/схема/движок),
  • двойная запись «вперёд» (если возможно),
  • переливаем историю по окнам,
  • сверяем агрегаты,
  • переключаем BI (VIEW/alias),
  • замораживаем v1 → удаляем позже.

 

Пересборка партиций

Только по окнам, ночью, с бэкапом/снапшотом, c контролями.

Риск: «ночью всё пересобрали, утром — пусто».
Митигация: чек-листы: бэкап, dry-run на стейдже, пост-мониторинг.

 

Производительность: выбор ORDER BY, размер блоков, merges

Быстрые выигрыши:

  • ORDER BY под реальные фильтры.
  • Партиции под частоту запросов (месяц/день).
  • Крупные батчи вставок (сотни тысяч/миллионы строк).
  • Избегайте FINAL в BI.
  • Мониторьте system.query_log, system.part_log, merges backlog.

 

Антипаттерны:

  • ORDER BY «как попало» (не отражает WHERE) → читаете лишнее.
  • Слишком частые мелкие вставки → тысячи parts, merges «задыхаются».
  • Summing на данных, которые «переигрывают» → удвоение сумм.

 

Кейс 1 (Retail): продажи и GM на wide-витринах

Задача: дашборды «день × магазин × категория», Net Sales, GM, GM%.

Модель:

  • mart_sales_wide — факт с нормализованными статусами и суммой в базовой валюте.
  • agg_retail_daily_state — суммы и GM как состояния.
  • VIEW vw_retail_daily — sumMerge + расчет GM%.

 

Риски:

  • Возвраты «задним числом» → ретро-окно 14–30 дней.
  • Себестоимость меняется → хранить cost_per_unit снэпшотом на день, ретро-пересчитать окно.
  • Длинные отчёты «за год» → хранить месячные агрегаты отдельно.

 

Кейс 2 (FinTech): транзакции, остатки, выручка

Задача: остатки по дням (полуаддитивная метрика), комиссионная выручка.

Модель:

  • mart_tx_wide — факт (дебет/кредит/fee/refund), amount_base.
  • agg_balance_daily_state — sumState(+/- amount) по дню и счёту.
  • agg_revenue_daily_state — sumState(fee) по продукту.

 

Риски:

  • Чарджбеки → ретро-окно пересчёта.
  • Валюты → фиксируйте правило «на дату операции» vs «на дату отчёта».
  • Сверка с GL (главная книга) → nightly баланс-тест.

 

Кейс 3 (Events/Telecom): поминутные KPI, перцентили

Задача: p95 latency, success_rate, объёмы по минутам × сотам.

Модель:

  • ingest из Kafka → events_wide.
  • agg_minute_state с sumState(ok/all) и quantileTDigestState(0.95).
  • VIEW агрегирует …Merge и считает долю.

 

Риски:

  • Бурсты и мелкие вставки → настраивать батчи, буферные таблицы.
  • Дубликаты событий → dedup по event_id до mart; Replacing как страховка.

 

«Политика» агрегатов и слоёв

  • Факты (wide/star) — первичный слой витрин: быстрое чтение, минимум JOIN.
  • Агрегаты-состояния — «рабочие лошади» под BI (устойчивость к повторной заливке).
  • Вьюхи — интерфейс для потребителя: …Merge, семантика, маскирование, RLS.
  • Агрегаты по периодам (неделя/месяц) — отдельные таблицы для регулярной отчётности.

 

Проверки качества (вокруг моделирования)

  • Нет дублей зерна в фактических витринах (причина — неверная уникальность/ingest).
  • Баланс MARTS vs CORE на окне (±допуск).
  • Плотность рядов по ключевым срезам (нет «дыр»).
  • Стабильность схем: additive-изменения, breaking — только через v2.
  • Guardrails производительности: ограничение периодов в BI, дефолтные фильтры.

 

Антипаттерны моделирования и быстрые фиксы

  1. Витрина копирует CORE (никаких pre-join/агрегатов).
    Фикс: денормализуйте под сценарии BI, материализуйте частые группировки.
  2. ORDER BY не по фильтрам.
    Фикс: переопределить под реальные WHERE, переложить v2-таблицей.
  3. Повсюду FINAL в чтении.
    Фикс: дисциплина записи/дедуп upstream, использование Aggregating-состояний.
  4. Summing на данных с ретро-правками.
    Фикс: Aggregating (state/merge) или rebuild окна.
  5. Мелкие партиции, много parts.
    Фикс: буферизация вставок, укрупнение партиций, контроль merges.
  6. JOIN «толстых» измерений на лету.
    Фикс: pre-join атрибутов «на дату факта» в широкую витрину/агрегат.

 

Практические «рецепты» (SQL-наброски)

Выбор ORDER BY через «трассировку» запросов

  1. Соберите из system.query_log топ WHERE-фильтров.
  2. Выделите общий префикс (обычно дата → разрез).
  3. Спроектируйте ORDER BY именно под этот префикс.

 

Стратегия «двух окон» обновления

  • Near-real-time: каждые N минут дозаливаем NOW()-2h..NOW().
  • Ночь: пересчитываем NOW()-30d..NOW()-1d (ретро-корректировки).

 

Side-by-side миграция ORDER BY

  • создать *_v2 с новым ORDER BY;
  • переливать партиции «месяц за месяцем» с контролем суммы;
  • переключить VIEW на v2;
  • v1 хранить 30–60 дней.

 

«Человеческая» стратегия выбора движка

  • MergeTree — если вставили и забыли, без правок.
  • ReplacingMergeTree(version) — если бывают апдейты по ключу (но избегайте FINAL).
  • SummingMergeTree — простые накопительные суммы без переигровок.
  • AggregatingMergeTree — когда важна устойчивость к повторной заливке или нужны uniq/quantile/avg с правильной агрегацией.
  • Collapsing/VersionedCollapsing — для сигналов +/- (дисциплина порядка!).

 

Мини-регламент проектирования новой витрины

  1. Сформулируйте вопрос и зерно (что в строке).
  2. Определите разрезы (какие атрибуты реально нужны в 90% запросов).
  3. Выберите модель: wide / star / гибрид.
  4. Спроектируйте партиции и ORDER BY под реальные фильтры.
  5. Решите, что материализовать (pre-join, агрегаты состояния).
  6. Определите инкремент и ретро-окно.
  7. Добавьте DQ-тесты и мониторинг (freshness, parts/merges).
  8. Пропишите миграции (как будете менять схему/формулы в будущем).
  9. Оформите паспорт метрик и VIEW (семантика для BI).

 

Ответы на частые вопросы

Нам нужна и ширина, и гибкость. Что делать?
— Делайте wide-витрины по доменам (продажи, веб-события) + тематические агрегаты; звезду держите в CORE и/или как вторую «служебную» модель для сложных расчётов.

Когда использовать проекции (projections)?
— Только после измерений «до/после». Это оптимизация, а не основа модели.

Как убрать FINAL, если данные «грязнятся»?
— Введите дедуп upstream (ключ+версия), ограничьте окно конкурирующих версий, переливайте «закрытые» партиции батчем, используйте Aggregating-состояния.

Сколько партиций делать?
— События с большим потоком — дневные; продажи — месячные. Дальше смотрите на merges backlog и SLA ретро-пересчётов.

 

Итог

Моделирование витрин под ClickHouse — это про баланс: удобство и скорость чтения ↔ управляемость изменений ↔ устойчивость к инкрементам.
Ключевые опоры:

  • Ясное зерно и осмысленная модель (wide/star/гибрид).
  • Материализации (pre-join, агрегаты-состояния) вместо тяжёлых запросов в BI.
  • Инкременты и ретро-окна вместо полных пересчётов.
  • Физика под запросы (партиции, ORDER BY, батчи).
  • Миграции v1→v2 без простоя и DQ/observability — как часть конструкции.

 

И дополнительные материалы:

1) Чек-лист проектирования витрины (версия 1.0)

Заполняется при старте любой новой витрины или при планировании v2.
Формат: да/нет + заметки + владелец.

A. Назначение и потребители

  • Бизнес-вопрос(ы), на которые отвечает витрина (2–3 конкретных запроса).
  • Основные потребители (BI/аналитики/сервисы), критичные дашборды.
  • Требуемая гранулярность: транзакция / минута / час / день / неделя / месяц.
  • Ожидаемые топ-срезы (до 5): пример — день → магазин → категория.

 

B. Контракты и семантика

  • Паспорт ключевых метрик (формулы, фильтры, календарь, валюта, зерно).
  • Календарь: григорианский / финансовый (4-5-4/4-4-5), TZ.
  • Валюта: «на дату операции» / «на дату отчёта» (нужны обе? отдельные VIEW).
  • Маппинг статусов источников → канонические статусы.
  • Окно корректировок (late events), дни: …; кто владелец решения.

 

C. Зерно, модель и ключи

  • Зерно vitrine-fact (что в 1 строке) описано однозначно.
  • Модель: wide / star / гибрид (обоснование выбора).
  • Ключи: бизнес-ключ и суррогат (нужно оба? зачем?).
  • SCD по измерениям: SCD0/1/2 и где живёт (CORE или MARTS).

 

D. Материализация

  • Какие JOIN делаем заранее (pre-join) и что остаётся для чтения.
  • Какие агрегаты считаем заранее (pre-aggregate), где будут храниться.
  • Механика устойчивости к повторным заливкам (Aggregating/…State/…Merge).

 

E. Физика ClickHouse

  • Партиционирование: месяц/день/неделя (обосновано нагрузкой).
  • ORDER BY соответствует типовым WHERE (реальный паттерн фильтров).
  • Вторичные индексы (data-skipping): minmax / bloom / set — только при доказанной пользе.
  • Движок таблицы: MergeTree / Replacing(version) / Summing / Aggregating — и почему.

 

F. Инкременты и ретро

  • Инкремент: как часто дозаливаем (каждые N минут/часов).
  • Ночной ретро-пересчёт: глубина окна (N дней/недель) и график.
  • Стратегия пересборки больших периодов (side-by-side).

 

G. SLA, DQ, Observability

  • Freshness SLA (днём/ночью), Availability, Consistency-порог (например, 0,2% с CORE).
  • Тесты DQ: баланс, дубли зерна, «дыры» в плотности, инварианты метрик.
  • Мониторинг: свежесть витрин, parts/merges, ошибки ingestion/MV.
  • Границы по умолчанию в BI (лимиты периода, дефолтные фильтры).

 

H. Доступ и безопасность

  • BI → только vw_* (семантические VIEW), прямой доступ к таблицам закрыт.
  • RLS по региону/тенанту (где и как реализовано).
  • Маскирование PII на уровне VIEW.

 

I. Релизы и версии

  • Процедура v1→v2: side-by-side, сравнение на окне, дата переключения, откат.
  • Документация: паспорт метрики, changelog, ссылки на дашборды.

 

2) Аудит текущих витрин: как быстро найти точки роста

Ниже — последовательность шагов, которые можно выполнить за 1–3 дня и получить план улучшений.

 

Сбор «рабочей нагрузки»

Цель: понять реальные фильтры/срезы и «тяжёлые» запросы.

  • Выгрузить из system.query_log:
    • топ запросов по read_bytes/read_rows/duration,
    • частые WHERE/GROUP BY паттерны,
    • частоту использования FINAL (тревожный маркер).
  • Классифицировать по витринам: какие поля реально фильтруются первыми.

 

Выход: матрица «витрина → топ-фильтры → соответствует ли текущему ORDER BY».

 

Состояние таблиц и вставок

Цель: найти part-explosion, болезненные merges.

  • Для каждой таблицы: активные parts по партициям, merges backlog, средний размер блока вставок.
  • Доля «мелких» вставок, число MV-пересчётов и их «дороговизна».

 

Выход: список таблиц-кандидатов на:

  • укрупнение партиций / буферизацию вставок,
  • точечный OPTIMIZE или переразбиение по ORDER BY.

 

Качество и стабильность

Цель: понять, где отчёты «гуляют».

  • Freshness vs SLA, баланс MARTS vs CORE (на окне), дубли зерна, «дыры» по датам.
  • Новые «сырые» статусы, не попавшие в канонические.

 

Выход: список обязательных DQ-фиксов и владельцы.

 

3) Предложения v2: общий конвейер решений

Выбор нового ORDER BY

Принцип: префикс ключа = самый частый «селективный» фильтр. Обычно:

  • события: (event_time, user_id[, …]);
  • продажи: (day, shop_id, sku_id) или (day, shop_id) — если SKU уходит в агрегат;
  • балансы: (day, account_id).

 

Алгоритм:

  1. Из query-лога — топ WHERE-паттернов на 80% трафика.
  2. Сформировать 2–3 кандидата ORDER BY (короткие префиксы).
  3. Прогнать «What-If» (на стейдже): время типовых запросов до/после на тестовом окне.
  4. Взять победителя, подготовить v2-таблицу и side-by-side миграцию.

 

Риски: слишком длинный ключ, много высококардинальных полей → рост метаданных и слабый эффект.
Как избежать: держать префикс коротким (2–3 поля), ориентироваться на реальный WHERE.

 

Выделение агрегатов (pre-aggregate)

Цель: разгрузить BI и стабилизировать формулы.

  • Частые группировки («день × магазин × категория») вынести в AggregatingMergeTree в виде состояний (sumState/uniq*/quantile*).
  • На чтении давать VIEW с …Merge — BI делает лёгкий SELECT без FINAL.

 

Когда делать отдельные агрегаты:

  • отчёт строится чаще 1–2 раз в день;
  • запросы сканируют «пол-таблицы» без фильтра;
  • считаются uniq/quantile — дорогие «на лету».

 

Переход с SummingMergeTree на AggregatingMergeTree

Зачем: устойчивость к повторной заливке и ретро-пересчётам.

  • Summing удваивает суммы при повторной загрузке периода.
  • Aggregating хранит состояния; повторная заливка не «накручивает» метрику — вы всегда «мерджите» состояния.

 

План перехода:

  1. Создать *_v2 на AggregatingMergeTree.
  2. Наполнить историю батчем INSERT … SELECT из «чистого» источника.
  3. Переключить инкремент: писать states.
  4. Создать VIEW с …Merge.
  5. Сравнить v1 vs v2 на окне, переключить BI, v1 — в read-only 30–60 дней.

 

Ретро-окно: как выбрать глубину и расписание

Подход:

  1. Постройте распределение задержек поступления событий: разница между «временем факта» и «временем прихода в MARTS».
  2. Возьмите квантили 95/99% → это разумные «границы» окна.
  3. Зафиксируйте: «оперативный инкремент — каждые 15 минут за ~2 часа; ночной ретро — за N дней; глубокая коррекция — по тикету и в выходные окна».

 

Рекомендованный старт:

  • eCom / события: 7–14 дней
  • Финансы / биллинг: 14–30 дней
  • Telecom / CDR: 1–3 дня (часто хватает), но глубже при пост-коррекциях

 

Шаблоны аудит-проверок и вспомогательных запросов

Ниже — «что именно смотреть», чтобы принять решения. (Сами SQL-наброски простые, подставите свои БД/таблицы.)

A. Частые фильтры и тяжёлые запросы

  • Топ по read_bytes, read_rows, duration_ms.
  • Распарсить WHERE и GROUP BY для 80% запросов.
    Цель: сформировать кандидатов ORDER BY и понять, какие агрегаты выделять.

 

B. Состояние частей и мерджей

  • parts по партициям (сортировка по убыванию), system.part_log событий мерджа за сутки, system.merges долго живущие операции.
    Цель: найти таблицы с part-explosion, определить необходимость буферизации вставок и укрупнения партиций.

 

C. FINAL-детектор

  • Доля запросов с FINAL по каждой таблице/VIEW.
    Цель: если FINAL нужен «для жизни» — обязательно переход на дисциплину записи или Aggregating.

 

D. DQ-срез

  • Баланс с CORE на «вчера»/на 7 дней.
  • Дубликаты grain (ключевые поля витрины).
  • Плотность (матрица дат × ключ — нет ли пропусков).
    Цель: убрать систематические источники «гуляющих» цифр до оптимизаций.

 

5) Типовые «рецепты v2» (примерные Before/After)

Кейc 1: Продажи (eCom/Retail)

Before

  • Таблица mart_sales_wide с ORDER BY (shop_id, sku_id, day); Summing-агрегат agg_sales_daily (удваивается при повторной загрузке); BI часто фильтрует по day BETWEEN … и shop_id IN (…).

 

After (v2)

  • Переложить ORDER BY на (day, shop_id, sku_id) — под реальный WHERE.
  • Заменить Summing на Aggregating с sumState(amount), sumState(qty);
  • Дать VIEW vw_sales_daily с sumMerge и календарём 4-5-4;
  • Ввести ретро-окно 14 дней: ночной пересчёт последних 14 дней, инкремент 15 минут за 2 часа;
  • В BI запретить FINAL (линтер), дефолтный фильтр «последние 28 дней».

 

Ожидаемый эффект: −40–70% времени на типовых отчётах, нулевая чувствительность к повторным заливкам, исчезновение «удвоений».

 

Кейc 2: События (продукт/маркетинг)

Before

  • ORDER BY (user_id, event_time); частые фильтры по времени; тяжёлые uniq/quantile на лету; много мелких частей из Kafka.

 

After (v2)

  • ORDER BY (event_time, user_id);
  • Выделить agg_events_minute_state с uniqCombinedState(user_id) и quantileTDigestState(0.95)(latency);
  • Настроить ingestion на микробатчи (размер блока ↑), буферную таблицу;
  • VIEW vw_kpi_minute — …Merge + rolling окна;
  • Ретро-окно 1–3 дня, ночной пересчёт, алерты «мелкие parts».

 

Ожидаемый эффект: стабильные p95/DAU, снижение латентности дашбордов ×2–5 раз.

 

6) Пошаговая миграция (side-by-side) — шаблон

  1. Создать v2-таблицу с новым ORDER BY/движком.
  2. Перелить историю по партициям (месяц/неделя), сверяя агрегаты.
  3. Включить двойную запись на период (если возможно): новые данные → v1 и v2.
  4. Построить VIEW для чтения из v2 (семантика неизменна по колонкам).
  5. Сравнить v1 vs v2 на окне (дельты в допуске), провести нагрузочный тест.
  6. Переключить BI на v2 (alias/view swap), v1 → read-only.
  7. Пост-мониторинг (freshness, ошибки, топ запросы), через 30–60 дней — удалить v1.

 

Guardrails:

  • никакого DROP до завершения окна мониторинга;
  • бэкапы/снапшоты партиций;
  • план отката (alias назад + временно отключить инкремент в v2).

 

7) Как выбрать глубину ретро-окна (короткая методика)

  1. Возьмите последнее 1–3 месяца логов поступления данных.
  2. Постройте гистограмму «задержка прибытия» (0–1 день, 1–2, 2–3, …).
  3. Выберите квантиль:
    • 95-й процентиль → «операционный» ретро (ночной),
    • 99-й → «глубокий» ретро (раз в неделю/в выходные).
  4. Зафиксируйте в паспорте метрик и в расписании джобов.

 

 

Arenadata QuickMarts (ADQM) — корпоративная платформа на базе ClickHouse для быстрого слоя витрин и near-real-time аналитики. Решает задачи «быстрых» дашбордов и API с низкой латентностью и высокой конкуррентностью, работает поверх вашего DWH/лейкхауса как serving-уровень. Даёт предсказуемую производительность на терабайтно-петабайтных объёмах за счёт колоночного хранения, компрессии и предагрегатов (Materialized Views, AggregatingMergeTree), подключается к Kafka/S3 и стандартным BI-инструментам по SQL/HTTP. Для корпоративных ИТ ADQM предлагает поддержку и SLA, отказоустойчивые кластеры (HA/DR), безопасность (RBAC, LDAP/OIDC, шифрование трафика и данных), мониторинг и резервное копирование. Платформа хорошо ложится на методологию курса: семантика vw_*, роллап-слои, NRT-ингест, SLO/наблюдаемость и «гвардейки» для BI/API. Итог — быстрый запуск витрин за недели, снижённые риски в проде и предсказуемая стоимость владения.

 

Узнать стоимость решенияЗапросить видео презентацию

← Предыдущая статья
Модуль 1. Бизнес-метрики и семантический слой витрин для ClickHouse
Следующая статья →
Модуль 3. Потоки данных, эксплуатация и надёжность ClickHouse-витрин
Запросить видео презентацию Запросить доступ к демо стенду online Узнать стоимость лицензий

Задать вопрос

loading...

Решения

Анализировать ФинансыУвеличивайте ПродажиОптимальный Склад и ЛогистикаМаркетинговые Метрики

Клиенты
  • В 2003 году Мерсико и пятью микрокредитными агентствами Мерсико было принято историческое решение о консолидации активов по всей территории Кыргызстана в целях образования национального финансового института по развитию сообществ - Компаньона. В октябре 2004 года Компаньон был зарегистрирован Национальным банком Кыргызской Республики.

  • ООО "Интернэшнл Ресторант Брэндс" – это крупнейший франчайзинговый партнер компании Yum! Brands Russia & CIS в России, отвечающий за рост и развитие бренда KFC на территории РФ. На сегодняшний день у компании более 350 ресторанов. Ежедневно в рестораны приходит 200 000+ гостей.

  • Торгово-производственному холдингу ТБМ, специализирующемуся на поставке комплектующих и фурнитуры для производства окон, дверей, стеклопакетов и мебели, был необходим аналитический инструмент для выявления узким мест и поиска зон роста бизнеса и, как результат, оптимизации процессов. Добиться этого можно было, только внедрив data-driven подход.

  • "Уральский банк реконструкции и развития" входит в топ-25 крупнейших банков России и список значимых кредитных организаций на рынке платежных услуг по версии ЦБ РФ.

  • Решения
    • Дистрибуция
    • Розничная торговля
    • Производство
    • Операторы связи
    • Страхование
    • Банки
    • Лизинг
    • Логистика
    • Нефтегазовый сектор
    • Медицина
    • Сеть ресторанов
    • E-Commerce
    • Энергетика
    • Фармацевтика
  • Услуги
    • Переход на отечественные BI и DWH
    • Консалтинг
    • Пилотный проект
    • Обучение и сертификация
    • Бесплатное обучение
    • Техническая поддержка
    • Технические задания
    • Сбор требований для проекта внедрения BI-системы
    • CI/CD для DWH
    • Аудит BI приложений
    • Выделенная команда
    • Настойка и поддержка баз данных
    • Разработка BI Стратегии
    • Styleguide для BI-системы
    • Как выбрать BI-систему
  • Платформы
    • FineBI
    • FineReport
    • FineDataLink
    • Коннекторы данных из 1С в BI
    • Airflow + NiFi
    • Visiology
    • Luxms BI
    • Modus BI
    • PIX BI
    • Arenadata
    • ClickHouse
    • Greenplum
    • Postgres Professional
    • Open-source BI: Superset/Metabase
    • Loginom
    • Yandex.DataLens
    • AI / Исскуственный интеллект
    • Optimacros
    • Шины данных
  • Курсы
    • Учебный курс Информационная грамотность
    • Учебный курс для бизнес-аналитиков
    • Учебный курс для системных аналитиков
    • Учебный курс по Data Governance
    • Учебный курс Как стать CDO
    • Учебный курс Современная архитектура хранилища данных
    • Учебный курс по Fine BI
    • Учебный курс по FineReport
    • Учебный курс по DWH
    • Учебный курс по Data Science (ML, AI)
    • Учебный курс по PostgreSQL
    • Учебный курс по Apache Airflow и NiFi
    • Учебный курс по Open-source BI
    • Учебный курс по ClickHouse
    • Учебный курс по DataLens
    • Учебный курс по Loginom
    • Учебный курс по Modus BI и ETL
    • Учебный курс по Visiology
    • Учебный курс по dbt
  • Функциональные решения
    • Создание Data Lake
    • Цифровая трансформация
    • Управление по KPI
    • Финансы
    • Продажи
    • Склад
    • HR
    • Маркетинг
    • Внутренний аудит
    • Категорийный менеджмент
    • S&OP и прогнозная аналитика
    • Геоаналитика
    • Цепочки поставок (SCM)
    • AutoML
    • Process Mining
    • Сквозная аналитика
  • Компания
    • О нас
    • Руководство
    • Новости
    • Клиенты
    • Скачать
    • Контакты
    • Политика конфиденциальности
RutubeVkontakteLinkedInYouTube
ООО "Би Ай Консалт",
ИНН: 7811437757,
ОГРН: 1097847154184
199178, Россия,
Санкт-Петербург,
6-ая линия В.О., Д. 63, 4 этаж
Тел: +7 (812) 334-08-01
Тел: +7 (499) 608-13-06
E-mail: info@biconsult.ru

 

 

 

 

 

×

Пользуясь сайтом, вы соглашаетесь с использованием cookies и политикой конфиденциальности.