Files
clickstream-data-platform/docs/labs/1-4-dq-errors-daily.md
T
ddadminandClaude Fable 5.1 d955f7d694 docs(labs): файлы ТЗ переименованы по схеме S-N-slug
- Зачем:
  - в docs/labs/ будет много заданий; номер ступени и номер задания в имени
    делают папку оглавлением программы и избавляют от поиска по README (#230).
- Что:
  - шесть ТЗ переименованы через git mv: 1-1…1-5 для ступени 1,
    2-1-superset-chart.md для ступени 2; факультатив superset-dashboard.md
    остался без номера.
  - обновлены ссылки в docs/labs/README.md, 2-1-superset-chart.md,
    docs/architecture/dds/session.md и пути в dags/homework_check.py.
  - правило имен для docs/labs/ в AGENTS.md переписано под S-N-slug.
- Проверка:
  - make lint; скрипт обхода относительных ссылок в docs/ и AGENTS.md —
    битых нет.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-06 09:09:14 -04:00

7.5 KiB

Задание 4: dm.dq_errors_daily

Чему учит: считать брак по дню загрузки и сохранять сводку дольше исходных строк. Пересборка всех партиций после удаления источника по TTL стирает историю, которую уже не восстановить.

Сначала прочитать

Роль витрины

Сводку открывают при росте брака в потоке: смотрят, каких ошибок стало больше и сколько строк забраковано. Причину конкретной ошибки исследуют в ods.event_errors_dist и ods.order_errors_dist, где есть сырой текст и координаты доставки.

Что сделать

Зерно — день загрузки × источник × класс брака. В источнике зерно — строка брака. Зерно новое, поэтому витрина хранится готовым агрегатом — см. «Как принято на ступени 1». Создайте пять объектов: dm.dq_errors_daily_rep / _dist, донор _stage_rep / _stage_dist и публичное представление dm.dq_errors_daily_v. Ключ партиции — день загрузки.

Состав колонок

Колонка Тип Значение
load_date Date День загрузки забракованной строки
source LowCardinality(String) event или order
error_class LowCardinality(String) Класс брака из таблицы ошибок
error_rows UInt64 Число забракованных строк
_load_id String Идентификатор запуска, собравшего день
_load_ts DateTime64(3, 'UTC') Время сборки

Вычислите load_date как toDate(_load_ts) из таблицы ошибок — это реальный день приема строки. Модельный день записан внутри исходной строки. Ее не удалось разобрать, поэтому надежно получить из нее день не получится. Служебная _load_ts витрины описывает сборку сводки; ее дата может отличаться от load_date.

У событий и заказов свои классы брака. source входит в зерно, чтобы одинаковые имена классов с разным смыслом не объединялись в одну строку.

Ритм пересборки

Брак хранится месяц по TTL, сырые данные — трое суток. Сводка хранится бессрочно: итоги нужны и после удаления исходных строк.

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

В течение текущих суток ошибки еще поступают: пересчитайте этот день на следующем прогоне.

Ключ шардирования

Выберите ключ самостоятельно. Классов брака у событий и заказов вместе меньше десятка. Объясните, насколько существенен перекос при таком объеме.

Ключ донора — тот же, что у цели (см. «Как принято на ступени 1» и раздел «Раскладка по шардам» справочника хранилища).

Источники: таблицы _dist

Только это задание читает данные не через _v: брак нужен для диагностики приема и не входит в бизнес-модель. Публичных представлений у таблиц ошибок нет, создавать их для задания не нужно. Источники:

  • ods.event_errors_dist — ошибки разбора событий;
  • ods.order_errors_dist — ошибки разбора слепка заказов.

Чтение локальной _rep даст строки одного шарда из двух: часть брака не попадет в сводку, хотя запрос выполнится без ошибки.

Типичная ошибка

Если заменить всю таблицу данными из нового донора, исчезнут итоги дней, истекших по TTL источника. Восстановить их неоткуда.

Как проверить себя

Деловой ключ — source и error_class внутри load_date. Проверяйте дни, оставшиеся хотя бы в одной таблице ошибок. Если дня за пределами TTL уже нет в источнике, это не ошибка: сверять его уже не с чем.

Посчитайте строки прямо в обеих таблицах ошибок и соедините результат с dm.dq_errors_daily_v полным внешним соединением по ключу. Затем посчитайте строки, где ключ отсутствует с одной из сторон или различается error_rows. Расхождений должно быть ноль.

Сумма error_rows по проверяемым дням равна общему числу строк в ods.event_errors_dist и ods.order_errors_dist. Если она примерно вдвое меньше, вероятная причина — чтение _rep вместо _dist.

Пустая витрина на чистом стенде — верный ответ: обе стороны пусты, расхождений ноль, проверка успешна. Требование хотя бы одной строки дало бы постоянную ошибку, которую со временем стали бы игнорировать.

Приемка

  • созданы пять объектов, донор объявлен через AS и шардируется ключом цели;
  • источники — таблицы _dist обоих видов брака;
  • прогон заменяет партиции только дней, еще имеющихся в источниках, и сохраняет дни за пределами их срока хранения;
  • задача dq_errors_daily в homework_check завершилась успешно, в том числе на чистом стенде без брака;
  • задача витрины добавлена в dm_transform.