docs(labs): упрощен язык учебных заданий

- Зачем: начинающим трудно читать задания из-за необъясненных терминов и неестественных формулировок.
- Что: переработаны вводная и 21 задание, названы темы разделов, объяснены термины и сокращены повторы; согласованы правила учебного текста и ссылки.
- Проверка: сохранены 25 блоков SQL и команд и таблицы состава колонок; проверены 153 локальные ссылки и 32 входящие ссылки на разделы; git diff --check прошел.
This commit is contained in:
ddadmin committed 2026-10-18 18:09:43 +02:00
1 parent 3c3eb825e1
commit 4693bc5af9
24 files changed
+782 -684

No files matched your search

+38 -36
View File
@@ -1,9 +1,10 @@
# Научите проверки замечать ошибки в заказах
# Проверки качества заказов
**Чему учит:** написать проверки заказов до изменения их обработки
и убедиться на намеренной ошибке, что проверки ее замечают.
Перед изменением обработки заказов вы добавите две проверки качества данных.
Затем намеренно испортите один заказ и убедитесь, что проверки обнаружили
ошибки.
## Сначала прочитать
## Подготовка
- [модель заказа DDS](../architecture/dds/order.md);
- [дневной конвейер](../architecture/etl.md#объём-прогона);
@@ -13,30 +14,29 @@
и на ее включение в [`dq_check`](../../dags/dq_check.py). Готового ответа для
двух проверок из этого задания в репозитории нет.
## Что предстоит сделать
## Новые проверки
Добавьте две проверки и включите их в даг:
- `sql/dq/order_items_total.sql` проверяет сумму позиций заказа;
- `sql/dq/orders_vs_ods.sql` сверяет DDS с его источником;
- `dags/dq_check.py` запускает обе проверки, публикует их строки в
- `dags/dq_check.py` запускает обе проверки, записывает их результаты в
`dm.dq_summary` и создает для них отдельные задачи.
Разбор ODS и сборку DDS вы перепишете в следующих заданиях. Здесь сохраните
их, даги загрузки, DDL, таблицы-доноры, Kafka и службы как есть.
их, даги загрузки, DDL, промежуточные таблицы, Kafka и службы как есть.
Перед опытами остановите автоматическое движение мира: поставьте `world_live`
на паузу и дождитесь завершения активных прогонов. До завершения опытов не
запускайте руками `world_next_day`, `world_live_day`, `world_initialize` и
`world_recreate`. Это условие стабильного модельного времени: одной паузы
`world_live` для него мало.
`world_recreate`, чтобы новые данные не меняли результат между проверками.
## Что будут проверять ваши запросы
## Требования к запросам
Чтобы `dq_check` мог запустить проверку, ее запрос возвращает по одной строке
на день с колонками `data_date`, `reference_rows`, `actual_rows`,
`failed_rows`, `diagnostics`. Даг сохраняет в `dm.dq_summary` только счетчики,
статус и координаты запуска. Примеры из `diagnostics` ищите в
статус и сведения о запуске. Примеры из `diagnostics` ищите в
журнале упавшей задачи Airflow. Ограничьте их тем же малым числом, что и
существующие запросы в `sql/dq/`.
@@ -44,46 +44,48 @@
Имя проверки - `order_items_total`. Для каждого заказа из `dds.order_v`
посчитайте сумму `item_price * item_quantity` и сравните ее с `items_total`.
`reference_rows` считает ключи со стороны `items_total`, `actual_rows` - ключи
со стороны вычисленной суммы, а `failed_rows` - несовпавшие значения. В
исправном наборе первые два счетчика равны; несовпадения сумм считает
`failed_rows`. Для диагностики достаточно `order_id`, ожидаемой суммы и
суммы позиций.
В `reference_rows` запишите число заказов со стороны `items_total`,
в `actual_rows` число заказов со стороны вычисленной суммы, в `failed_rows`
число заказов, у которых суммы не совпали. На исправных данных первые два
счетчика равны, а `failed_rows` равен нулю. Для примеров расхождений
достаточно `order_id`, значения `items_total` и вычисленной суммы позиций.
Проверка относится к типизированному разбору массива `items` на границе
ODS -> DDS. Скидку, доставку и равенство `total` здесь проверять не нужно.
Проверка поможет заметить ошибки разбора `items` при переносе заказа
из ODS в DDS. Скидку, доставку и равенство `total` здесь проверять не нужно.
### DDS против ODS
### Полнота заказов в DDS
Имя проверки - `orders_vs_ods`. Источник модели DDS здесь - текущее состояние
`ods.order_v`. С ним вы и сравниваете DDS; обращаться к внутреннему состоянию
генератора для этой проверки не нужно.
Одним запросом соберите обе стороны на зерне дня заказа и сравните:
Одним запросом рассчитайте итоги каждого дня заказа в обоих слоях и сравните:
- число заказов;
- максимальный `updated_at`.
День ODS вычисляется в `Europe/Samara`, как `order_date` в DDS. Область
проверки - объединение дней обеих сторон, включая день, который полностью
пропал из одного слоя. Перед сравнением приведите времена к одному часовому
поясу. `reference_rows` - число заказов ODS, `actual_rows` - число заказов DDS,
а `failed_rows` равен единице для дня, где расходится хотя бы одно значение.
День заказа в ODS вычисляйте в `Europe/Samara`, как `order_date` в DDS.
Проверьте все дни, которые есть хотя бы в одном слое: так вы заметите день,
целиком пропавший из другого. Перед сравнением приведите времена к одному
часовому поясу. `reference_rows` содержит число заказов ODS, `actual_rows`
число заказов DDS. В `failed_rows` запишите 1, если за день расходится
хотя бы одно значение, и 0, если оба совпали.
Обе стороны распределены по `order_id`. Дневные агрегаты соедините через
`GLOBAL FULL OUTER JOIN` с `join_use_nulls = 1`, как в существующих сверках.
Если разбор ODS и сборка DDS одинаково потеряют строку, слои останутся равны
по этой проверке. Общая потеря при разборе проявится в отдельном балансе по
`_load_id` из [следующего задания](5-2-order-parsing.md).
Если строка потерялась при разборе в ODS, она не попадет и в DDS. Эта проверка
не заметит потерю: данные слоев совпадут. В [следующем задании](5-2-order-parsing.md)
вы отдельно сравните число исходных строк с числом разобранных заказов
и ошибок за один запуск, обозначенный `_load_id`.
## Получите красный и зеленый результаты
## Проверка на намеренных ошибках
Сначала запустите `dq_check` на нетронутых данных. Обе новые задачи должны
завершиться успешно, а в `dm.dq_summary_v` у обоих имен не должно быть
нарушенных дней.
дней с расхождениями.
Выберите оплаченный заказ из последнего слепка с непустым массивом позиций и
сохраните его `order_id` и `order_date`. Подключитесь к первой ноде из DBeaver
сохраните его `order_id` и `order_date`. Подключитесь к первому узлу из DBeaver
по [инструкции из README](../../README.md#подключиться-из-dbeaver) под
пользователем `etl`. Прибавьте одну копейку к `items_total` этого заказа в
локальной таблице `dds.order_rep` на всем кластере:
@@ -102,7 +104,7 @@ SETTINGS mutations_sync = 2;
Запустите `etl_pipeline`. Текущее окно заказов будет заново собрано из ODS, и
исходная строка вернется в DDS. Повторный `dq_check` должен дать зеленый
результат для нового сторожа.
результат для новой проверки.
Теперь удалите тот же заказ из `dds.order_rep` на всем кластере:
@@ -118,9 +120,9 @@ SETTINGS mutations_sync = 2;
Если `orders_vs_ods` не обнаружил удаление, исправьте запрос до следующего
задания.
## Как проверить себя
## Проверка результата
В `dm.dq_summary_v` должны быть зелены обе новые и пять прежних проверок:
В `dm.dq_summary_v` обе новые и пять прежних проверок должны быть успешны:
```sql
SELECT check_name, sum(failed_rows) AS failed_rows, groupUniqArray(status)
@@ -132,12 +134,12 @@ ORDER BY check_name;
Проверка суммы должна охватывать каждый день `dds.order_v`. Сверка слоев
должна охватывать объединение дней ODS и DDS, включая дни только одной стороны.
## Завершите опыт
## Завершение работы
После восстановления заказа и успешного `dq_check` можно закончить работу или
перейти к разбору заказов, оставив модельное время на паузе.
## Что должно получиться
## Результат работы
- [ ] две новые проверки запускаются в `dq_check`, а их дневные результаты
появляются в `dm.dq_summary`;