Модуль 20. Итоговая аттестация и template-пак
Это «выпускной» модуль: вы доказываете навыки на реальном стенде, а на выходе получаете набор шаблонов и автоматизаций, чтобы быстро запускать новые домены витрин на ClickHouse.
Цель и формат
Цель: закрепить результат курса и оставить «конструктор», с которым команда сможет за 1–2 недели поднять слой витрин для нового домена.
Формат аттестации = 3 части:
- Онлайн-квиз (закрытые/полуоткрытые вопросы) — проверка теории и инженерной смекалки.
- Защита Capstone — демонстрация рабочего контура «CORE→MARTS→vw_*→BI/API» с DQ, наблюдаемостью и SLA.
- DR-тест на стенде — восстановление из backup + smoke-тесты.
Критерии прохождения:
- Квиз ≥ 80%.
- Capstone — «зелёный» по SLA/DQ (см. чек-лист ниже).
- DR-тест — успешно выполнен (RPO/RTO в допусках).
Онлайн-квиз: структура, сложность, примеры
Разделы и вес
- Моделирование и семантика (М1–М3) — 20%.
- Инкременты/стриминг/агрегации (М4, М14) — 25%.
- Производительность/стоимость/хранение (М5, М10, М16) — 25%.
- Безопасность/операционная модель (М15, М18, М19) — 20%.
- Наблюдаемость/DQ (М7, М17) — 10%.
Типы вопросов
- Multiple choice с 1–2 правильными.
- Match («сопоставь инструмент и задачу»).
- Код-сниппеты SQL/DDL — «что делает», «чем заменить».
- Мини-кейсы: выбрать стратегию ORDER BY/TTL/ретро-окна.
Примеры (выдержки)
-
Какой движок для минутных KPI с uniq/quantile?
a) SummingMergeTree
b) AggregatingMergeTree (верно)
c) ReplacingMergeTree
d) MergeTree + FINAL -
Чем пагинация «по ключу» лучше OFFSET?
Ответ: не сканирует «всё до», стабильна при вставках, использует составной упорядоченный ключ. -
Что сломает SLA быстрее всего?
a) DISTINCT на сырых фактах (да)
b) sumMerge() по состояниям
c) LIMIT BY
d) dictGet()
Защита Capstone: требования к демонстрации
Что именно показать (минимум жизнеспособный контур)
- Данные: Retail или SaaS (как в М12/М13) на 30–90 дней, 10^8 строк+ (или пропорционально стенду).
- Хранилище: MARTS (wide + agg-state), rollup (minute/hour/day), семантика vw_*.
- Инкремент/стриминг: batch/CDC или Kafka→staging→MV→agg_minute_state.
- DQ/Observability: freshness, баланс vs CORE/GL, инварианты; Grafana/SQL-отчёт.
- Безопасность: RBAC, RLS, маскирование, профили/квоты.
- BI/API: 1–2 тайла в BI или REST-эндпоинт /api/v1/kpi?from&to&… (JSON/Parquet).
- Документация: паспорта метрик (YAML), lineage, статический сайт (М17).
SLA/DQ чек-лист защиты
- Freshness NRT-витрин ≤ 5 мин (p95); дневные ≤ 60 мин (p95).
- Баланс vs CORE/GL за окно 30 дней: ≤ 0.2%.
- Вьюхи без FINAL/SELECT *; тяжёлые метрики — через …State/…Merge.
- BI/API → только db_sem.vw_*; RLS/маскирование включены; профили/квоты применены.
- Observability: нет «part explosion»; merges/replication без бэклога.
Оценивание защиты (рубрика)
|
Пункт |
Баллы |
|---|---|
|
Архитектура и физика данных (ключи, партиции, rollup) |
15 |
|
DQ/наблюдаемость (freshness, баланс, инварианты, алерты) |
15 |
|
Производительность (p95 плиток/эндпоинтов, read_bytes) |
10 |
|
Безопасность (RLS/маскирование/квоты) |
10 |
|
Документация как код (YAML, lineage, превью в PR) |
10 |
|
BI/API (функциональность и «гвардейки») |
10 |
|
Ответы на вопросы, осознание рисков/компромиссов |
10 |
|
Итого |
80 |
Порог «зачёт защиты» — ≥60/80 и все SLO/DQ в «зелёной» зоне.
DR-тест: сценарий и критерии
Сценарий (пример на 60–90 минут)
- Сделать BACKUP актуальных схем/данных (если не включён по расписанию).
- Смоделировать аварийную потерю одной ноды или удаление партиции.
- Выполнить RESTORE на тестовом стенде.
-
Прогнать smoke-тесты:
- доступность db_sem.vw_*;
- freshness в пределах SLO;
- баланс vs CORE/GL (за вчера).
- Отчитаться о RPO/RTO.
Критерии
- RPO ≤ 15 минут, RTO ≤ 60 минут (или как в вашей политике).
- Все smoke-тесты зелёные.
- Исполнение runbook’а без «ручной магии».
Template-пак: что входит
Шаблоны готовы для копирования в ваш репозиторий; всё — «док как код» и сразу под CI.
Структура
template-pack/
infra/ # IaC/конфиги (настройки CH, storage_policy)
sql/
tables/ # DDL wide/agg-state/stage/quarantine
views/ # vw_*.sql (семантика, прологи для доков)
dicts/ # словари (FX/календарь/статусы)
mv/ # Kafka→staging, staging→fact, fact→agg_state
metrics/ # YAML-паспорта метрик (шаблоны)
dq/ # тесты SQL (freshness/balance/invariants)
ci/
actions/ # GitHub Actions: линтер, тесты, деплой, доки
sql-linters/ # правила: no FINAL, enforce time filter, …
docs_build.py # генерация сайта (MkDocs)
lineage_extract.py
validate_metrics.py
api/
nginx/ # proxy_cache, limit_req, cache-key с auth
queries/ # параметризованные SQL для эндпоинтов
tools/
bench/ # скрипты бенчей (М16) + отчёт
audit/ # запросы по query_log (дорогие, PII)
retro/ # REPLACE PARTITION, окна, throttle
docs/ # каркас статического сайта (MkDocs)
checklists/ # go-live, security, observability, DR-day
README.md
Основные файлы (фрагменты)
Storage policy и TTL (NVMe→warm→S3):
<!-- infra/storage_policy.xml -->
<storage_configuration>
<disks>
<disk name="hot" path="/var/lib/clickhouse/" />
<disk name="warm" path="/var/lib/clickhouse-warm/" />
<disk name="s3" type="s3" endpoint="https://s3..." access_key_id="..."/>
</disks>
<policies>
<policy name="tiered">
<volumes>
<volume name="hot"><disk>hot</disk></volume>
<volume name="warm"><disk>warm</disk></volume>
<volume name="cold"><disk>s3</disk></volume>
</volumes>
<move_factor>0.2</move_factor>
</policy>
</policies>
</storage_configuration>
Шаблон agg-state и vw_*:
CREATE TABLE agg_sales_daily_state ( day Date, shop_id UInt32, category_id UInt32, amount_state AggregateFunction(sum, Decimal(18,2)), qty_state AggregateFunction(sum, Int64), buyers_state AggregateFunction(uniqCombined, UInt64) ) ENGINE = AggregatingMergeTree PARTITION BY toYYYYMM(day) ORDER BY (day, shop_id, category_id) SETTINGS storage_policy='tiered'; CREATE OR REPLACE VIEW db_sem.vw_retail_daily AS /* owner: retail_analytics@company.com; metrics: [RETAIL_NET_SALES_DAY]; grain:[day,shop_id,category_id] */ SELECT day, shop_id, category_id, sumMerge(amount_state) AS net_sales, sumMerge(qty_state) AS qty, uniqCombinedMerge(buyers_state) AS buyers, net_sales / NULLIF(qty,0) AS aov FROM db_marts.agg_sales_daily_state GROUP BY day, shop_id, category_id;
YAML паспорта метрики (шаблон):
id: RETAIL_NET_SALES_DAY title: Net Sales per Day version: 1 owner: retail_analytics@company.com grain: [day, shop_id, category_id] calendar: gregorian currency: operation_date source_view: db_sem.vw_retail_daily definition_sql: "net_sales=sumMerge(amount_state)" acceptance: freshness_sla_minutes: 60 balance_vs_core_rel: 0.002 retro_window_days: 30
CI: линтер SQL и «стоп-релизы», доки-превью (фрагмент GH Actions):
name: CI
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: python ci/validate_metrics.py
- run: python ci/lineage_extract.py
- run: python ci/lint_sql.py # проверка FINAL/SELECT * / time filter
- run: python ci/check_error_budget.py # блок релизов при исчерпании
docs-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pip install mkdocs-material sqlglot pyyaml graphviz
- run: python ci/docs_build.py && mkdocs build --strict
- uses: actions/upload-pages-artifact@v3
with: { path: 'site' }
API: Nginx кеш/лимиты/ключ кэша с auth (см. М15) — готовы шаблоны api/nginx/….
DQ-набор: SQL-тесты freshness/balance/invariants + скрипт отчёта (Markdown).
Sizing/TCO: Excel/Markdown-калькулятор (формулы из М16).
Чек-листы:
- go-live.md — перед продом (SLO, DQ, RLS, квоты, доки).
- security.md — PII-реестр, маскирование, TTL/retention (М18).
- observability.md — алерты/дашборды (lag, parts, merges, replication, read_bytes).
- dr-day.md — сценарии и контрольный лист.
Процедура аттестации: шаги и тайминг
До экзамена (T-14…T-1 дней)
- Развернуть стенд (минимум 3 ноды CH + Keeper) и завести тестовые данные.
- Импортировать template-pack в свой репозиторий; подключить CI/доки-превью.
- Согласовать SLO/окна и «красные линии».
Экзаменационный день (T0)
- Квиз — 40–60 минут.
- Защита Capstone — 45 минут демонстрации + 15 минут вопросы.
- DR-тест — 60–90 минут, затем короткий отчёт.
После (T+1…T+3)
- Получить обратную связь и итоговый протокол.
- При необходимости — ремедиэйшн-план и повтор части проверки (до 2 недель).
Оценка и сертификация
Итоговый балл = Квиз (40%) + Capstone (50%) + DR-тест (10%).
Порог сертификации — ≥ 80% и отсутствие «красных» пунктов в чек-листах SLA/DQ/безопасности.
Градации:
- Pass — ≥ 80%.
- Pass with distinction — ≥ 90% и «зелёные» SLO все 7 дней dual-run.
- Remediate — < 80% или провал DR — устранить замечания, повтор.
Типичные ошибки на защите и как их избежать
|
Ошибка |
Проявление |
Профилактика/фикс |
|---|---|---|
|
DISTINCT/квантили «на лету» |
p95 взлетает, SLA нет |
Храните состояния (…State) и читайте …Merge; вынесите в rollup |
|
FINAL в продуктивных вьюхах |
резкий рост read_bytes, таймауты |
Линтер CI: запрет FINAL; переписать запись/агрегации |
|
Узкий/неверный ORDER BY |
FULL SCAN партиций, медленно |
Перепроектировать ключ под реальные WHERE; v2 таблица |
|
Нет RLS/маскирования |
доступ к «чужим» данным |
Включить ROW POLICY, vw_*_masked, квоты |
|
Нет ретро-окна |
«теряются» поздние события |
Ночное REPLACE PARTITION окна 14–30 дней |
|
S3 без кэша |
джиттер latency |
filesystem cache, горячее окно на NVMe |
|
Док-сайт не совпадает с продом |
«разные правды» |
Генерация доков из YAML/SQL, превью на PR, no-owner→no-merge |
Кейсы разбора на защите
- «Упал CR в пиковый час» — покажите как через Observability (freshness/lag, read_bytes, parts/merges) находите узкое место и докажите, что BI-плитки читают rollup, а не сырые факты.
- «Сошёлся баланс vs CORE на 0.5%» — опишите ретро-пересборку 30-дневного окна и как фиксируете версию метрики в YAML и changelog.
- «Партнёр просит API без лимитов» — покажите Nginx cache-key с auth, limit_req, профили/квоты и Parquet-экспорт вместо «безлимитного» JSON.
Риски template-подхода и митигации
|
Риск |
Суть |
Митигация |
|---|---|---|
|
«Натягивание» шаблонов |
копипаста без адаптации |
В README — раздел «как адаптировать»: календарь/валюта/зерно/ключ; обзвон домена |
|
Устаревшие шаблоны |
версии CH/коннекторов меняются |
Версионирование template-pack, релизы /v1.2, changelog, автопроверки |
|
«Учёба ради теста» |
узнали ответы, не поняли причин |
Ротация вопросов/датасетов, кейсы «почему так» |
|
Безопасность «для галочки» |
RLS/маски не везде |
CI-линтер: «BI только vw_*», PII-реестр (М18), контрактные тесты |
|
Недооценка стоимости |
TCO «плавает» |
Workbook (М16), контролируемое горячее окно, бенчи при каждом релизе схемы |
Вспомогательные материалы, которые отдаём
- Template-pack (структура выше) + README.md пошаговой сборки.
- Банк вопросов для квиза (вариативный, 150+ шт, метки по темам/сложности).
- Скрипты генерации данных и бенчей (М16), отчётов DQ/SLO (SQL + Markdown).
- Гайды: «Как защищать Capstone», «DR-день за час», «Как читать query_log».
- Шаблоны отчёта об аттестации и сертификат прохождения.
Итог
После Модуля 20 у вас есть две вещи:
- Подтверждённая компетенция: вы показали, что держите витринный слой как сервис — со SLA, DQ, безопасностью, наблюдаемостью и DR.
- Инженерный конструктор: template-пак, который ускоряет первые спринты на новых доменах — от DDL и MV до API, DQ, CI/CD и доков.
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. Итог — быстрый запуск витрин за недели, снижённые риски в проде и предсказуемая стоимость владения.



