Зачем: студенту нужен понятный путь от сохраненного состояния к SQL-сравнению без доступа технической учетной записи к изменению хранилища. Что: добавлен student с чтением источников и записью только в default; лабораторная сохраняет заказы и итоги в две локальные таблицы. Обновлены настройка доступа и программа, уточнено округление productPrice. Проверка: DDL и INSERT SELECT под student, пустое наблюдение, восемь переходов сохраненной истории и запрет вставки в пять прикладных баз на обеих нодах. config-test, lint стенда и генератора, 54 ссылки, независимое ревью.
30 KiB
Программа учебных лаб
Эта спека собирает программу лаб из инвентаризации сюжетов, выполненной в тикете #201. Тикет спеки — #202, карта — #182.
Статус: спека принята владельцем; судьба идей-кандидатов решена здесь поименно.
1. Кому и зачем
Менти уже прошел большой теоретический курс ClickHouse объемом около 60 часов. Он знает устройство системы в теории, но почти ничего не делал своими руками.
Поэтому в программе нет вводного блока с теорией. Здесь теория становится ремеслом: менти руками осваивает слои хранилища, DQ, оркестрацию и идемпотентность.
Обещание программы: менти проходит конвейер стенда автором, а не читателем.
2. Устройство программы: основная программа и факультативы
У частей программы два статуса, третьего нет.
Основная программа — обязательная часть. Менти проходит ее целиком и по порядку, потому что каждая следующая ступень опирается на предыдущую. От ступени к ступени растет самостоятельность: сначала менти получает готовые ТЗ с готовыми сторожами (DQ-проверками), а затем строит сторожей сам.
Факультативы — необязательные лабы. Они собраны в тематические разделы, чтобы менти мог одним взглядом выбрать интересное. Для каждого раздела указано, после какой ступени основной программы он открывается.
В программе используются четыре формы заданий:
- построить свое по ТЗ — рядом есть образец, но готового ответа нет;
- вычитание — SQL готовой трансформации удаляется и пишется заново, а даги остаются как несущая инфраструктура;
- собери рядом — менти строит свою копию результата рядом с нетронутым стендовым и сверяет их построчно;
- расследование — данные уже лежат на стенде или стенд намеренно ломается, а менти ищет причину и объясняет ее.
Как писать задания
Пишите для учащегося: объясняйте, чему он научится, зачем нужны действия и как понять результат. Историю разработки оставляйте за пределами задания.
«Как проверить себя» описывает действия для проверки и поиска ошибок. «Что должно получиться» — результат работы и то, что учащийся теперь может объяснить. Если проверка уже встроена в шаги упражнения, повторять ее отдельным разделом не нужно.
Остальные заголовки и структуру выбирайте по содержанию. Образцы — задания про дашборд Superset и расследование подключения.
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. Разбери сырые события и сверь результат со стендом
Менти пакетно разбирает срез событий из STG в собственную таблицу и построчно сверяет результат с нетронутым стендовым ODS. Урок — изучить разбор потока отдельно от живого приема и использовать стендовый результат как образец для сверки. Матвью разбора остаются несущей стеной: их пересоздание молча теряет сообщения.
Форма — «собери рядом». Обратная связь — построчная сверка двух разборов. Ее границы называются прямо: срок работы ограничен окном хранения сырых данных, а содержимое неопорных колонок можно сравнить только со стендовым разбором, не с независимым эталоном.
Ступень 7. Мониторинг: куда смотреть
Сначала менти знакомится с панелями стенда. Затем проводит два безопасных
расследования. В первом он находит в query_log, что верх списка тяжелых
запросов занимает сам мониторинг. Во втором объясняет, почему свежесть второго
источника выглядит как пила, а не как линия, и выбирает правильный слой данных
для панели.
Форма — расследование. Обратная связь — найденные запросы и верное объяснение формы графика и выбора слоя. Ломательные опыты остаются в факультативе «Что делать, когда стенд сломался». Урок ступени — куда и на что смотреть в живой системе.
Общее правило вычитания: ТЗ каждого вычитания на ступенях 4 и 5 включает
пересчет ключа шардирования по hostName(). Счетные сверки читают _dist,
поэтому учитывают строку даже на чужом шарде и остаются зелеными: они не видят
саму ошибку раскладки.
4. Факультативы — пять разделов
Ниже перечислены сюжеты, их уроки и принятые решения по форме заданий. Исходный материал и способы проверки — в инвентаризации.
Почему выручка не сходится
Этот раздел рекомендован первым из факультативов и открывается после ступени 1 основной программы. Шесть сюжетов собраны в четыре лабораторные: три расследования готовых данных и одно наблюдение во времени. Опоздания, изменение выручки и история отмен используют одну историю заказов, поэтому для них выбрана общая работа вместо трех отдельных.
Результат расследования — запрос сверки и инженерное решение, подтвержденное данными: выбор источника, ключа, полей для точного расчета или правила пересчета и хранения истории. Объяснение суммы служит проверкой решения. Вариант закончить работы только объяснением показателей отклонен: он смещал акцент в анализ отчетов. Постройка новых DAG и подключение проверок к конвейеру оставлены основной программе, чтобы факультативы не повторяли ее задания.
- Куда пропали покупки (#186). Сверка по номерам заказов обосновывает источник витрины и условие окончательной проверки полноты. Счетчики событий помогают обнаружить расхождение, но не устанавливают место потери.
- Почему повтор покупки завышает выручку (#187). Учащийся собирает расчет с одной строкой на заказ, проверяет ключ и полноту набора номеров, отличает его зерно от зерна исходных событий.
- Какая позиция объясняет разницу в сумме. Сверка позиций обосновывает выбор исходных полей и типа денег, отделяет ошибку собственного разбора от различия данных события и заказа.
- Почему вчерашняя выручка меняется сегодня (#188). Наблюдение опозданий и смены статусов обосновывает правило пересчета при ежедневной загрузке без пропусков. Учащийся определяет момент закрытия дня и требования к истории для воспроизведения расчета и проверки факта оплаты.
В четвертой лабораторной выбрано собственное наблюдение: учащийся продвигает
мир по одному дню через Airflow и сохраняет результаты после обновления витрин
в две локальные таблицы ClickHouse под student: состояния заказов и итоги
наблюдений. Сравнение выполняется SQL-запросами в том же подключении DBeaver.
Учащийся может писать только в default; источники доступны ему на чтение.
Отдельная строка итогов фиксирует и наблюдение без заказов. Экспорт в CSV
отклонен как основной способ: он требовал неописанного перехода к другому
инструменту или обратному импорту файлов.
Готовые слепки и сочетание готового примера с собственным наблюдением
отклонены: нужную историю можно получить на стенде и самому увидеть,
как новые данные меняют уже рассчитанный отчет.
День считается закрытым после получения и обработки последнего слепка семидневного окна изменяемости; этот слепок доставляется следующим модельным днем. Одного совпадения сумм в соседних наблюдениях для такого вывода недостаточно. История отмен тоже имеет границу: оплата и отмена между двумя дневными слепками могут остаться невидимыми. Отсутствие наблюдаемой оплаты не доказывает, что оплаты не было.
Тонкий анализ данных
Открывается после ступени 1 основной программы.
- Что мы знали о пользователе в тот день (#145). Текущее знание и знание на дату дают разные отчеты; сведения из будущего меняют прошлое.
- Добавь названия регионов в отчет (#143). Менти собирает свой словарь по
образцу каталога и обогащает отчет через
dictGet.
Superset и BI
Открывается после ступени 2 основной программы.
- Свой дашборд. Менти использует результат ступени 2, собирает отчет из пяти своих витрин и подтверждает выводы запросами. Пользовательские объекты остаются отдельно от стендовых.
- В DBeaver работает, в Superset нет. Менти создает отдельное представление на первой ноде и расследует ошибку чтения из Superset, подключенного ко второй. Опыт заканчивается объяснением, исправлением DDL и удалением учебного объекта.
Задания самостоятельны: расследование использует готовую витрину стенда.
Отсутствие объекта проверяется в SQL Lab, поскольку создание физического
датасета может остановиться раньше, чем появится график. Чтение только одного
шарда остается материалом инженерного раздела: это отдельная причина
неполного результата, которую добавление ON CLUSTER само по себе не устраняет.
Технический опыт проверен 2026-09-13 на ClickHouse 26.3.17.56: локальное
представление недоступно пользователю bi на второй ноде; после создания
на кластере обе ноды возвращают тот же счет, что исходная витрина.
Инженерия стенда
Открывается после ступени 1 основной программы. Сюжеты про переигрывание дня и пошардовую атомарность раскроются полнее после ступени 4, когда менти уже спускался в DDS.
- Как принимать данные из Kafka: потоком или слепком. Поток и слепок требуют разных способов приема и дают разную наблюдаемость.
- Почему данные попадают на свои шарды независимо от ноды чтения. Нода-потребитель может меняться, а раскладку строк определяет ключ шардирования.
- Почему вторая группа потребителей дублирует поток. Еще одна группа потребителей создает еще одну полную копию потока.
- Как заметить пропущенные сообщения по офсетам. Разрыв в офсетах показывает потерю, которую трудно заметить по самим данным.
- Почему сырые данные удаляются по времени загрузки. Очистка сырых данных идёт по времени загрузки, а не по модельному дню.
- Куда попадают битые строки. Годные строки и брак делят поток без
пропусков и пересечений; менти подкладывает по строке каждого класса брака
событий и находит их в
ods.event_errors_dist. - Какая версия заказа считается текущей. Версию заказа задает слепок
источника, а
FINALскрывается за представлением. - Почему один момент попадает в разные дни. Один момент дает разные дни в разных поясах, поэтому день и пояс нужно называть явно.
- Проверь, как стенд разобрал JSON в
ecommerce. Типизированный разбор может молча подменить ошибку значением, поэтому менти сам разбирает сырой JSON и сравнивает результат с массивами стенда. - Как конвейер восстанавливает пропущенный день. Конвейер сам находит дыру и определяет объем повторной обработки по состоянию хранилища.
- Что будет, если день заменился не на всех шардах. Замена дня завершается отдельно на каждом шарде, поэтому целостность результата подтверждает отдельная сверка.
- Как обновлять витрину без полной пересборки (#149) — повышенная сложность. Экономия на пересчете требует хранить историю изменений, которую полная пересборка стирает.
Что делать, когда стенд сломался
Открывается после ступени 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 приемка этой спеки закрыла;
исполнение ведет отдельная карта — тикет #206 (решение тикета #203).