# Задание 4: `dm.dq_errors_daily` **Чему учит:** считать брак по дню загрузки и сохранять сводку дольше исходных строк. Пересборка всех партиций после удаления источника по `TTL` стирает историю, которую уже не восстановить. ## Сначала прочитать - [«Хранилище и его слои»](../handbook/storage-layers.md); - [«Потоки Airflow и даги модельного времени»](../handbook/airflow-dags.md). ## Роль витрины Сводку открывают при росте брака в потоке: смотрят, каких ошибок стало больше и сколько строк забраковано. Причину конкретной ошибки исследуют в `ods.event_errors_dist` и `ods.order_errors_dist`, где есть сырой текст и координаты доставки. ## Что сделать Зерно — **день загрузки × источник × класс брака**. В источнике зерно — строка брака. Зерно новое, поэтому витрина хранится готовым агрегатом — см. [«Как принято на ступени 1»](README.md#как-принято-на-ступени-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»](README.md#как-принято-на-ступени-1) и раздел «Раскладка по шардам» [справочника хранилища](../architecture/storage.md)). ## Источники: таблицы `_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`.