Files
clickstream-data-platform/docs/specs/2026-09-01-labs-program.md
T
ddadmin 4fd872f296 docs(specs): спека программы учебных лаб — хребет и ветки
- Зачем:
  - тикет #202 карты #182: собрать из инвентаризации #201 программу лаб
    целиком — состав, порядок, формы и судьбу идей-кандидатов.
- Что:
  - создан docs/specs/2026-09-01-labs-program.md: хребет из семи
    обязательных шагов и пять тематических разделов необязательных лаб;
  - узаконены границы вычитания по потокам и поименные резолюции идей
    #143, #145, #148, #149, #186, #187, #188;
  - записаны отклоненные варианты оси прогрессии и границы спеки (#203).
- Проверка:
  - вычитка владельцем (спека принята), слепое ревью фактов против
    инвентаризации и доков — все находки закрыты.
2026-09-01 08:45:43 -04:00

23 KiB

Программа учебных лаб

Эта спека собирает программу лаб из инвентаризации сюжетов, выполненной в тикете #201. Тикет спеки — #202, карта — #182.

Статус: спека принята владельцем; судьба идей-кандидатов решена здесь поименно.

1. Кому и зачем

Менти уже прошел большой теоретический курс ClickHouse объемом около 60 часов. Он знает устройство системы в теории, но почти ничего не делал своими руками.

Поэтому в программе нет вводного блока с теорией. Здесь теория становится ремеслом: менти руками осваивает слои хранилища, DQ, оркестрацию и идемпотентность.

Обещание программы: менти проходит конвейер стенда автором, а не читателем.

2. Устройство программы: хребет и ветки

У частей программы два статуса, третьего нет.

Хребет — обязательная часть. Менти проходит его целиком и по порядку, потому что каждый следующий шаг опирается на предыдущий. По хребту растет самостоятельность: от готовых ТЗ с готовыми сторожами (DQ-проверками) к заданиям, где сторожей менти строит сам.

Ветки — необязательные лабы. Они собраны в тематические разделы, чтобы менти мог одним взглядом выбрать интересное. У каждого раздела есть точка прицепа — шаг хребта, после которого материал уже доступен.

В программе используются четыре формы заданий:

  • построить свое по ТЗ — рядом есть образец, но готового ответа нет;
  • вычитание — SQL готовой трансформации удаляется и пишется заново, а даги остаются как несущая инфраструктура;
  • собери рядом — менти строит свою копию результата рядом с нетронутым стендовым и сверяет их построчно;
  • расследование — данные уже лежат на стенде или стенд намеренно ломается, а менти ищет причину и объясняет ее.

3. Хребет — семь шагов

Шаг 1. Витрины: пять заданий слоя DM

Первая часть программы опирается на шесть существующих заданий из docs/labs/. Пять ТЗ по витринам входят в первый шаг хребта и выполняются как есть. Их точечный пересмотр — работа реализации. Шестое задание, про свой дашборд в Superset, остается необязательной лабой в ветке «Superset и BI». Набор уроков пяти витрин уже записан в их общем описании: от слоя как договора до честных имен показателей.

Форма — построить свое по ТЗ. Обратную связь дает даг homework_check.

Шаг 2. Свой отчет в Superset

Менти строит один график в Superset поверх витрины, которую сделал на первом шаге. Урок — увидеть, как собственный результат из хранилища становится отчетом в BI, не превращая знакомство с инструментом в отдельный большой проект.

Форма — построить свое по ТЗ. Результат проверяется глазами. ТЗ для этого нового шага предстоит написать при реализации программы. Полный собственный дашборд остается необязательной лабой в разделе «Superset и BI».

Шаг 3. Нарежь сессии сам

До того как открыть стендовый SQL нарезки сессий в DDS, менти самостоятельно делит события на визиты. Сначала он сравнивает число своих сессий с эталоном VisitID. Затем вручную соединяет свою сессию с эталонной и поштучно разбирает хотя бы одно расхождение границ. Урок — счет называет проблему, но причину приходится искать в отдельных строках.

Форма — построить свое по ТЗ и провести расследование. Обратная связь состоит из счетной сверки с VisitID и ручного сопоставления границ.

Шаг 4. Перепиши нарезку стенда

Менти удаляет и заново пишет SQL нарезки сессий DDS: расчет объема, пересборку и замену. Урок — изменить расчетную сущность внутри готового конвейера и проверить ее внешним эталоном. Это единственный поток, для которого инвентаризация подтвердила вычитание без оговорок: здесь есть настоящие места для ошибок, а проверка не содержит готового ответа.

Форма — вычитание. Обратную связь дают dq_check и поштучная сверка, построенная на третьем шаге.

Шаг 5. Сначала сторож, потом ломай: заказы

Сначала менти строит две недостающие DQ-проверки. Первая утверждает равенство «цена × количество = items_total». Вторая сверяет слой с источником по дням. Их менти строит по образцу пяти стендовых проверок в sql/dq/. Обе проверки должны покраснеть на управляемой ошибке. Затем менти вручную подкладывает по строке каждого класса брака, проверяет разбор и убирает эти строки за собой.

Только после этого он вычитает разбор заказов ODS order_parse и трансформацию заказа DDS. Урок — сторожа строят до рискованного изменения, а не после первой поломки.

Форма — построить свои проверки по ТЗ, провести управляемое расследование и выполнить вычитание. Обратную связь дают две новые проверки, баланс годных и ошибочных строк по срезу и существующие сверки заказов.

Шаг 6. Собери разбор рядом: события ODS

Менти пакетно разбирает срез сырья событий в собственную таблицу и построчно сверяет результат с нетронутым стендовым ODS. Урок — изучить разбор потока отдельно от живого приема и использовать стендовый результат как образец для сверки. Матвью разбора остаются несущей стеной: их пересоздание молча теряет сообщения.

Форма — «собери рядом». Обратная связь — построчная сверка двух разборов. Ее границы называются прямо: срок работы ограничен окном хранения сырья, а содержимое неопорных колонок можно сравнить только со стендовым разбором, не с независимым эталоном.

Шаг 7. Мониторинг: куда смотреть

Сначала менти знакомится с панелями стенда. Затем проводит два безопасных расследования. В первом он находит в query_log, что верх списка тяжелых запросов занимает сам мониторинг. Во втором объясняет, почему свежесть второго источника выглядит как пила, а не как линия, и выбирает правильный слой данных для панели.

Форма — расследование. Обратная связь — найденные запросы и верное объяснение формы графика и выбора слоя. Ломательные опыты остаются в ветке «Поломки и runbook». Урок шага — куда и на что смотреть в живой системе.

Общее правило вычитания: ТЗ каждого вычитания на шагах 4 и 5 включает пересчет ключа шардирования по hostName(). Счетные сверки читают _dist, поэтому учитывают строку даже на чужом шарде и остаются зелеными: они не видят саму ошибку раскладки.

4. Ветки — пять разделов

Ниже перечислены только названия сюжетов и их уроки. Материал, формы и способы проверки остаются в инвентаризации.

Сверка и деньги

Эта ветка рекомендована первой среди необязательных. Точка прицепа — после шага 1 хребта: материал живет на стенде с этапа 6.

  • Недосчет трекера и правило «поведение — по трекеру, деньги — по бэкенду» (#186). Разрыв воронки подтверждений показывает потерянные события и границу доверия к двум источникам.
  • Бизнес-дубль и наивная выручка (#187). Технический и деловой дубли — разные вещи, поэтому одинаковые строки и одинаковая покупка требуют разных правил.
  • Дельта суммы, объясненная до копейки сравнением позиций. Расхождение суммы нужно разложить до конкретной вычеркнутой позиции и объяснить до копейки.
  • Две дороги отмены и история версий. Текущее состояние не заменяет историю, а некоторые различия после истечения срока сырья уже не восстановить.
  • Опоздавшие заказы и закрытое окно (#188). Отчет за день становится окончательным лишь после того, как источник больше не может изменить этот день.
  • Дыхание выручки. Внутри окна изменяемости выручка движется, а после закрытия дня фиксируется.

Тонкий анализ данных

Точка прицепа — после шага 1 хребта.

  • Склейка идентичностей во времени (#145). Текущее знание и знание на дату дают разные отчеты; сведения из будущего меняют прошлое.
  • Справочник регионов (#143). Менти собирает свой словарь по образцу каталога и обогащает отчет через dictGet.

Superset и BI

Точка прицепа — после шага 2 хребта.

  • Свой дашборд. Готовая лаба docs/labs/superset-dashboard.md учит хранить пользовательские объекты отдельно от стендовых.
  • Ловушка ноды 2. Забытый ON CLUSTER может остаться незаметным до тех пор, пока дашборд не обратится ко второй ноде.

Инженерия стенда

Точка прицепа — после шага 1 хребта. Сюжеты про переигрывание дня и пошардовую атомарность раскроются полнее после шага 4, когда менти уже спускался в DDS.

  • Push против pull — два способа принять топик. Поток и слепок требуют разных способов приема и дают разную наблюдаемость.
  • Кто читал топик и куда легли данные. Нода-потребитель может меняться, а раскладку строк определяет ключ шардирования.
  • Вторая consumer group — дубли. Еще одна группа потребителей создает еще одну полную копию потока.
  • Дырка в офсетах. Разрыв в офсетах показывает потерю, которую трудно заметить по самим данным.
  • Две оси времени. Очистка сырья живет по времени загрузки, а не по модельному дню.
  • Предикат и его буквальное отрицание. Годные строки и брак делят поток без пропусков и пересечений; менти подкладывает по строке каждого класса брака событий и находит их в ods.event_errors_dist.
  • Три времени и версия-наблюдение. Версию заказа задает слепок источника, а FINAL скрывается за представлением.
  • Часовой пояс как способ смотреть на время. Один момент дает разные дни в разных поясах, поэтому день и пояс нужно называть явно.
  • Сырое против разобранного (ecommerce). Типизированный разбор может молча подменить ошибку значением, и его нужно сверять с источником.
  • Переиграть день X. Конвейер сам находит дыру и определяет объем повторной обработки по состоянию хранилища.
  • Атомарность — пошардовая. Замена дня завершается отдельно на каждом шарде, поэтому целостность результата подтверждает отдельная сверка.
  • Инкремент против пересборки (#149) — повышенная сложность. Экономия на пересчете требует хранить историю изменений, которую полная пересборка стирает.

Поломки и runbook

Точка прицепа — после шага 7 хребта; весь раздел — повышенная сложность.

  • Keeper — общая память кластера. Остановка keeper связывает состояние DDL и репликации с тем, что видно на панелях и в системных таблицах.
  • Повисший DDL. Очередь распределенного DDL показывает путь запроса и ответ каждой ноды.

Итог ветки — runbook, которого сейчас не хватает стенду. Менти пишет его по результатам опытов, и документ остается в проекте.

5. Границы вычитания по потокам

Подробное сравнение потоков и таблица доказательств остаются в инвентаризации. Спека берет это сравнение за основу и проводит свои границы. Без оговорок вычитанию отдаются только сессии DDS. Заказы можно вычитать лишь после самодельных сторожей. Для событий ODS выбрана форма «собери рядом»; вычитание здесь отклонено. Прием STG и забор заказов остаются несущей стеной и доступны только для расследований. Карту идентичностей спека решает не отдавать вычитанию; причины этого выбора названы в следующем разделе.

6. Что не вошло

Вычитание стендовых витрин DM не входит в программу. Оно повторяет урок готового ядра DM, а открытые сверочные запросы в sql/dq/ почти дословно содержат ответ.

Форма «собери рядом» для карты идентичностей тоже не входит. Независимого эталона нет, а слабые инварианты проверяют допустимость связей, но не полноту. Аналитический урок идентичности уже несет склейка во времени (#145) в ветке «Тонкий анализ данных».

Сюжеты, которые инвентаризация относит к лекциям, остаются лекциями: Sign и CollapsingMergeTree, топологии в бою и идентичность «как в бою». Эта спека оставляет их в списке опорных точек раздела 12 спеки v2.

7. Судьба идей-кандидатов

Эти решения закрывают тикеты после приемки спеки:

  • #143, справочник регионов — вошла в ветку «Тонкий анализ данных».
  • #145, склейка во времени — вошла в ветку «Тонкий анализ данных».
  • #148, домашки ниже DM и вычитание — вошла в программу шагами 4–6 хребта. Форму для каждого потока уточнила инвентаризация #201: вычитание, «сначала сторож» или «собери рядом».
  • #149, инкрементальный daily_traffic — вошла в ветку «Инженерия стенда» с пометкой «повышенная сложность».
  • #186, воронка подтверждений — вошла в ветку «Сверка и деньги».
  • #187, бизнес-дубль — вошла в ветку «Сверка и деньги».
  • #188, опоздавшие заказы — вошла в ветку «Сверка и деньги».

8. Отклоненные варианты оси

  • Чистое «снизу вверх»: STG → ODS → DDS → DM. Оно начинает программу с самого тяжелого по инфраструктуре участка. Внизу быстро кончается эталон обратной связи, а вычитание вслепую заставляет переписывать слой, которым менти еще не пользовался.
  • Два прохода: сначала расследования снизу вверх, потом постройка сверху вниз. Пролог из восьми расследований откладывает первый собственный результат. Вместо этого расследования разнесены по веткам и доступны в своих точках прицепа.
  • Сюжетами поперек слоев. Такой порядок ломает принятое решение, по которому готовые задания открывают программу, и превращает путь в сетку зависимостей.

9. Границы спеки и что дальше

Спека не переписывает существующие ТЗ в docs/labs/ и общий README; точечный пересмотр относится к реализации.

Реализация программы тоже находится за границей спеки. В нее входят новые ТЗ для шагов 2–7 хребта и веток, а также отражение порядка программы в docs/labs/README.md. Докуда карта #182 ведет работу дальше, решает тикет #203.