docs(labs): упрощен язык учебных заданий
- Зачем: начинающим трудно читать задания из-за необъясненных терминов и неестественных формулировок. - Что: переработаны вводная и 21 задание, названы темы разделов, объяснены термины и сокращены повторы; согласованы правила учебного текста и ссылки. - Проверка: сохранены 25 блоков SQL и команд и таблицы состава колонок; проверены 153 локальные ссылки и 32 входящие ссылки на разделы; git diff --check прошел.
This commit is contained in:
1 parent
3c3eb825e1
commit
4693bc5af9
24 files changed
+782
-684
No files matched your search
@@ -1,9 +1,10 @@
|
||||
# Перепишите сборку заказов в DDS
|
||||
# Сборка заказов в DDS
|
||||
|
||||
**Чему учит:** настроить пересборку заказов по состоянию ODS и DDS
|
||||
и проверить, что она восстанавливает пропущенный день за пределами текущего окна.
|
||||
Вы перепишете загрузку заказов из ODS в DDS и выбор дней для пересчета.
|
||||
Затем удалите данные за один из прошлых дней и проверите, что ваша
|
||||
загрузка восстановила их.
|
||||
|
||||
## Сначала прочитать
|
||||
## Подготовка
|
||||
|
||||
- [проверки заказов](5-1-order-checks.md);
|
||||
- [разбор заказов в ODS](5-2-order-parsing.md);
|
||||
@@ -11,7 +12,7 @@
|
||||
- [дневной конвейер](../architecture/etl.md#объём-прогона);
|
||||
- [раскладку по шардам](../architecture/storage.md#раскладка-по-шардам).
|
||||
|
||||
## Что предстоит сделать
|
||||
## Файлы для изменения
|
||||
|
||||
Удалите готовый SQL и перепишите только три файла:
|
||||
|
||||
@@ -19,18 +20,18 @@
|
||||
- `sql/dds/order_rebuild.sql`;
|
||||
- `sql/dds/order_replace.sql`.
|
||||
|
||||
Даг `dds_transform`, DDL, донор, ODS и обе проверки из первого задания
|
||||
Даг `dds_transform`, DDL, промежуточную таблицу, ODS и обе проверки из первого задания
|
||||
оставьте как есть. Перед началом убедитесь, что пробные строки предыдущего
|
||||
задания удалены, а семь DQ дают зеленый результат.
|
||||
задания удалены, а семь проверок качества дают зеленый результат.
|
||||
|
||||
Поставьте `world_live` на паузу и дождитесь завершения активных прогонов. До
|
||||
завершения опыта не запускайте `world_live_day`, `world_initialize` и
|
||||
`world_recreate`. `world_next_day` понадобится только в явно указанном ниже
|
||||
случае.
|
||||
|
||||
## Как даг запускает ваши запросы
|
||||
## Выполнение запросов в Airflow
|
||||
|
||||
Сохраните интерфейс `dds_transform`:
|
||||
Даг `dds_transform` ожидает от файлов следующие параметры и результаты:
|
||||
|
||||
| Файл | Вход | Результат |
|
||||
|---|---|---|
|
||||
@@ -38,39 +39,46 @@
|
||||
| `order_rebuild.sql` | `{first_day:Date}`, `{last_day:Date}`, `{load_id:String}` | выбранные дни в `dds.order_stage_dist` |
|
||||
| `order_replace.sql` | день в `{{ params.day }}` | партиция дня в `dds.order_rep` |
|
||||
|
||||
Объем состоит из текущего окна источника и хвоста от первого дня, который есть
|
||||
в ODS, но отсутствует в DDS. Текущее окно дают строки последнего
|
||||
`snapshot_date`: их минимальный и максимальный день заказа. Если источник
|
||||
пуст, `order_scope.sql` не возвращает строку. Если дыр нет, `first_day` равен
|
||||
началу окна. Если дыра старше, непрерывный отрезок начинается с нее.
|
||||
Сначала определите дни, за которые заказы еще могут измениться. Возьмите
|
||||
строки с последним `snapshot_date` и найдите минимальную и максимальную
|
||||
дату заказа. Этот диапазон далее называется текущим окном источника.
|
||||
|
||||
Затем найдите первый день, который есть в ODS, но отсутствует в DDS.
|
||||
Если он раньше начала текущего окна, начните расчет с него. Иначе начните
|
||||
с начала окна. Полученная дата станет `first_day`, а конец окна `last_day`.
|
||||
Один запуск пересчитывает все дни между ними. Если источник пуст,
|
||||
`order_scope.sql` не возвращает строку.
|
||||
|
||||
`order_rebuild.sql` сначала очищает все партиции `dds.order_stage_rep` на
|
||||
кластере, затем записывает в `dds.order_stage_dist` весь выбранный отрезок. Он
|
||||
читает текущее состояние `ods.order_v`, вычисляет `order_date`, переводит
|
||||
времена в `Europe/Samara`, разбирает `items` в три параллельных массива и
|
||||
ставит координаты запуска.
|
||||
заполняет служебные поля запуска.
|
||||
|
||||
Запись через Distributed должна завершиться до замены и использовать ключ
|
||||
целевой таблицы для раскладки строк. Способ собрать весь отрезок внутри файла
|
||||
выберите сами.
|
||||
Дождитесь записи всех строк на шарды через Distributed перед заменой партиций.
|
||||
Строки должны распределяться по ключу целевой таблицы. Способ рассчитать
|
||||
выбранные дни внутри файла выберите сами.
|
||||
|
||||
`order_replace.sql` работает с локальными `dds.order_rep` и
|
||||
`dds.order_stage_rep` на всем кластере. `REPLACE PARTITION` переносит готовую
|
||||
дневную партицию из донора и оставляет донор на месте. Структура, ключи и
|
||||
политика хранения совпадают: DDL объявляет донор через `AS dds.order_rep`.
|
||||
`dds.order_stage_rep` на всем кластере. `REPLACE PARTITION` заменяет дневную
|
||||
партицию основной таблицы готовой партицией из промежуточной. Промежуточная
|
||||
партиция при этом сохраняется. Структура, ключи и политика хранения таблиц
|
||||
совпадают: DDL создает промежуточную через `AS dds.order_rep`.
|
||||
|
||||
## Восстановите ближайший закрытый день
|
||||
## Восстановление пропущенного дня
|
||||
|
||||
Найдите последний по дате день DDS, который лежит левее начала текущего окна
|
||||
ODS. Это ближайший к окну закрытый день: его удаление показывает расширение
|
||||
объема на дыру без пересборки всей истории.
|
||||
Найдите самый поздний день DDS перед началом текущего окна ODS. Заказы за этот
|
||||
день уже не меняются, поэтому он считается закрытым. Удалив его, вы проверите,
|
||||
что ваш запрос заметил пропуск и включил этот день в расчет.
|
||||
|
||||
Если такого дня еще нет, один раз продвиньте мир через `world_next_day`,
|
||||
дождитесь `orders_ingest`, затем запустите `etl_pipeline`. После этого снова
|
||||
зафиксируйте модельное время до конца опыта и выберите ближайший закрытый день.
|
||||
оставьте модельное время неизменным до конца опыта и выберите этот день.
|
||||
|
||||
Сохраните для него число заказов и контрольную сумму деловых полей без
|
||||
`_load_id` и `_load_ts`. Удалите только его партицию:
|
||||
Сохраните для него число заказов и контрольную сумму их полей, исключив
|
||||
служебные `_load_id` и `_load_ts`. Контрольная сумма позволит проверить,
|
||||
что после восстановления значения остались прежними. Удалите только
|
||||
партицию выбранного дня:
|
||||
|
||||
```sql
|
||||
ALTER TABLE dds.order_rep ON CLUSTER clickstream_cluster
|
||||
@@ -90,29 +98,30 @@ DROP PARTITION 'YYYY-MM-DD';
|
||||
прогона число заказов и контрольная сумма выбранного дня должны совпасть с
|
||||
сохраненными.
|
||||
|
||||
## Проверьте раскладку и повтор
|
||||
## Распределение по шардам и повторный запуск
|
||||
|
||||
Напишите отдельный запрос к `dds.order_dist`, который получает фактическую
|
||||
ноду через `hostName()`, вычисляет ожидаемую по `cityHash64(order_id) % 2` и
|
||||
считает несовпадения по каждой ноде. Остаток 0 соответствует
|
||||
`clickhouse-01`, остаток 1 - `clickhouse-02`. На обеих нодах число строк на
|
||||
чужом шарде должно быть нулевым. Счетные DQ читают Distributed-таблицы и такую
|
||||
ошибку раскладки не обнаруживают.
|
||||
Напишите отдельный запрос к `dds.order_dist`, который получает фактический
|
||||
узел каждой строки через `hostName()`, вычисляет ожидаемый по
|
||||
`cityHash64(order_id) % 2` и считает несовпадения по каждому узлу.
|
||||
Остаток 0 соответствует `clickhouse-01`, остаток 1 - `clickhouse-02`.
|
||||
На обоих узлах число строк на чужом шарде должно быть нулевым.
|
||||
Проверки количества строк читают данные со всех шардов через Distributed
|
||||
и такую ошибку не обнаруживают.
|
||||
|
||||
Запустите `etl_pipeline` еще раз при неизменном модельном времени. Группа
|
||||
заказов снова должна пересобрать текущее изменяемое окно. Контрольные суммы
|
||||
деловых полей остаются прежними, а все семь проверок дают зеленый результат.
|
||||
полей заказов остаются прежними, а все семь проверок дают зеленый результат.
|
||||
|
||||
## Завершите опыт
|
||||
## Завершение работы
|
||||
|
||||
После восстановления партиции и успешных проверок снимите `world_live`
|
||||
с паузы, если он работал до упражнения.
|
||||
|
||||
## Что должно получиться
|
||||
## Результат работы
|
||||
|
||||
- [ ] вы переписали три файла `sql/dds/order_*.sql`, сохранив остальные
|
||||
части стенда;
|
||||
- [ ] вы удалили ближайший к окну закрытый день и увидели ошибку DQ до
|
||||
- [ ] вы удалили ближайший к окну закрытый день и увидели ошибку проверки до
|
||||
восстановления;
|
||||
- [ ] ваш расчет выбрал `first_day` с удаленного дня и заменил партиции
|
||||
всего отрезка до конца окна;
|
||||
@@ -120,4 +129,4 @@ DROP PARTITION 'YYYY-MM-DD';
|
||||
с сохраненными значениями; они совпали;
|
||||
- [ ] `order_items_total`, `orders_vs_ods` и пять прежних проверок успешны;
|
||||
- [ ] ваш запрос с `hostName()` не нашел заказов на чужом шарде;
|
||||
- [ ] повторный `etl_pipeline` сохранил деловые данные, проверки прошли.
|
||||
- [ ] после повторного `etl_pipeline` поля заказов остались прежними, проверки прошли.
|
||||
Reference in new issue
Block a user