docs(warehouse): объяснены расчет строк и замена дневных разделов
Зачем: выражения «собираются в донор» и «публикуются дни» требовали знать устройство конвейера до чтения объяснения. Что: описаны назначение промежуточных таблиц и последовательность расчета, записи и замены разделов. Перечитаны остальные объяснения: выбор дней, разворачивание позиций заказа, проверка сессий и повтор запуска. Проверка: make lint, git diff --check, локальные ссылки и якоря. SQL без комментариев и AST обоих дагов без строк документации не изменились. Refs: #249
This commit is contained in:
1 parent
5f317ba8d2
commit
086007fbd4
12 files changed
+216
-166
No files matched your search
+39
-22
@@ -1,21 +1,23 @@
|
||||
# Дневной конвейер трансформаций
|
||||
|
||||
Даг `etl_pipeline` собирает модель DDS, обновляет витрины DM и проверяет
|
||||
результат. Здесь описаны запуск, выбор дней и публикация данных.
|
||||
результат. Здесь описаны запуск, выбор дней и запись результата в таблицы.
|
||||
Состав моделей — в [справочниках DDS](dds/README.md) и [DM](dm.md).
|
||||
|
||||
## Форма
|
||||
|
||||
`etl_pipeline` последовательно запускает `dds_transform`, `dm_transform`
|
||||
и `dq_check`. Каждый следующий даг начинается после успеха предыдущего.
|
||||
Для этого `TriggerDagRunOperator` ждет завершения созданного им запуска;
|
||||
его ошибка завершает ошибкой и соответствующую задачу конвейера.
|
||||
Для этого `TriggerDagRunOperator` ждет завершения запущенного им дага.
|
||||
Если тот завершился ошибкой, задача ожидания в конвейере тоже завершится
|
||||
ошибкой.
|
||||
Поведение проверено через Context7 по документации Airflow 3.x (3.1.6).
|
||||
|
||||
У этих дагов нет расписания. Их вызывает конвейер; для отдельного разбора
|
||||
можно запустить даг слоя вручную. У каждого разрешен один активный запуск:
|
||||
два запуска одного дага не должны одновременно заполнять общий донор.
|
||||
Внутри дага модели собраны в отдельные задачи и группы задач.
|
||||
два запуска одного дага используют одни промежуточные таблицы и могли бы
|
||||
стереть результаты друг друга. Расчет каждой модели выполняется отдельной
|
||||
задачей или группой задач.
|
||||
|
||||
## Три пути запуска
|
||||
|
||||
@@ -40,9 +42,11 @@ world_next_day ─────> источники без ETL
|
||||
|
||||
Объем прогона — дни, которые обрабатывает один запуск. Даты передавать
|
||||
не нужно: даги определяют их по состоянию таблиц и `world_position`.
|
||||
Например, после генерации семи дней без ETL один запуск соберет все семь.
|
||||
Например, после генерации семи дней без ETL один запуск рассчитает сессии
|
||||
за все семь дней.
|
||||
|
||||
Сессии собираются от первого отсутствующего дня до последнего прожитого.
|
||||
Для расчета сессий выбираются дни от первого, за который в DDS еще нет
|
||||
сессий, до последнего прожитого.
|
||||
`world_position` хранит номер следующего дня для генерации, поэтому
|
||||
последний прожитый день равен `min(EventDate) + world_position - 1`.
|
||||
Начало календаря берется из ODS; события ранних дней там не удаляются по TTL.
|
||||
@@ -52,9 +56,10 @@ world_next_day ─────> источники без ETL
|
||||
|
||||
Для заказов диапазон задает последний принятый слепок ODS. Среди строк
|
||||
с максимальной `snapshot_date` выбираются самая ранняя и самая поздняя
|
||||
даты оформления заказа. Эти дни еще могут измениться. Если в DDS
|
||||
отсутствует более ранний день, который есть в ODS, левая граница
|
||||
расширяется до него. Все дни отрезка пересобираются.
|
||||
даты оформления заказа. Состояние заказов за эти дни еще может измениться.
|
||||
Если в ODS есть заказы за более ранний день, а в DDS за него нет строк,
|
||||
начало диапазона сдвигается до этого дня. Запрос заново рассчитывает
|
||||
заказы за все дни выбранного отрезка.
|
||||
|
||||
Позиция мира для выбора дней заказов не подходит: с событиями дня D
|
||||
приходит слепок за D−1. Объем рассчитывается по принятым строкам ODS;
|
||||
@@ -62,8 +67,8 @@ world_next_day ─────> источники без ETL
|
||||
|
||||
Карта идентичностей пересчитывается целиком. Витрины выбирают дни
|
||||
по своим источникам — см. [ритм пересборки DM](dm.md#ритм-пересборки).
|
||||
Поиск отсутствующих дней проверяет только наличие даты: частично
|
||||
заполненный день требует отдельной проверки.
|
||||
Если за день сохранилась хотя бы одна строка, запрос не считает его
|
||||
пропущенным. Полноту данных проверяют отдельно.
|
||||
|
||||
## Готовность источника
|
||||
|
||||
@@ -96,17 +101,29 @@ world_next_day ─────> источники без ETL
|
||||
не добавляет копии деловых строк. Служебные `_load_id` и `_load_ts`
|
||||
при новой сборке меняются.
|
||||
|
||||
Для дневных таблиц порядок такой: `scope` выбирает даты, `rebuild` очищает
|
||||
донор и собирает в него весь диапазон, затем отдельные задачи `replace`
|
||||
публикуют дни через `REPLACE PARTITION`. Донор — служебная таблица с той же
|
||||
структурой и раскладкой по шардам, что у цели. Запись в `_stage_dist`
|
||||
с `distributed_foreground_insert = 1` дожидается доставки строк перед заменой.
|
||||
Результат дневного расчета сначала записывается в промежуточную таблицу.
|
||||
Она нужна, чтобы читатели продолжали видеть прежние данные, пока новые
|
||||
еще рассчитываются. Например, для сессий это `dds.session_stage_rep`,
|
||||
а основная таблица — `dds.session_rep`.
|
||||
|
||||
Замена выполняется на локальных `_rep` с `ON CLUSTER`. Она атомарна
|
||||
на каждом шарде: читатель видит старую или новую партицию. Единой
|
||||
транзакции для двух шардов и всех дней нет. Если замена прошла только
|
||||
на одном шарде, другой может сохранить прежние данные. Повтор задачи
|
||||
`replace` с тем же готовым донором повторит замену без добавления копий.
|
||||
Задачи выполняются в таком порядке:
|
||||
|
||||
1. `scope` выбирает даты для расчета.
|
||||
2. `rebuild` очищает промежуточную таблицу, рассчитывает строки за выбранные
|
||||
дни и записывает их через `_stage_dist`. Настройка
|
||||
`distributed_foreground_insert = 1` заставляет вставку дождаться
|
||||
доставки строк на шарды.
|
||||
3. `replace` заменяет в основной таблице раздел за каждый выбранный день
|
||||
готовым разделом промежуточной таблицы. Раздел таблицы называется
|
||||
партицией; для замены используется `REPLACE PARTITION`.
|
||||
|
||||
Структура и распределение строк по шардам у двух таблиц должны совпадать.
|
||||
Замена выполняется на локальных `_rep` с `ON CLUSTER`. На каждом шарде
|
||||
читатель видит либо старый, либо новый раздел целиком — это атомарность
|
||||
замены. Общей транзакции для двух шардов и всех дней нет: при сбое один
|
||||
шард может уже содержать новый результат, а другой — прежний. Повторить
|
||||
`replace` можно, пока промежуточная таблица хранит тот же результат;
|
||||
копии строк в основной таблице от этого не появятся.
|
||||
|
||||
Новый запуск всего конвейера заново выбирает дни. Он не обязан повторить
|
||||
все дни неудачного запуска: если дата уже есть в целевой таблице, поиск
|
||||
|
||||
Reference in new issue
Block a user