Files
airflow-greenplum/docs/bookings_to_gp_dds.md
T
ddadmin 35144e49f6 docs: согласованы руководства загрузок и учебный маршрут
Руководства STG/ODS/DDS/DM сверены с действующими SQL и DAG,
ожидания учебных заглушек связаны с ТЗ. Самопроверка заданий
отделена от проверок разработки и исторических планов.

Для dim_routes закреплено обновление описательных полей только
у открытых версий. SQL, DAG, DDL и настройки стенда не менялись.

Проверки: make lint; make test (4 passed, 14 skipped); карта;
292 локальные ссылки; маршрут чтения и карта в Chromium.
Живой ETL не запускался.
2026-09-20 15:53:39 -04:00

9.9 KiB
Raw Blame History

Загрузка ODS → DDS: bookings_to_gp_dds

DAG наполняет измерения и собирает dds.fact_flight_sales. Одна строка факта соответствует сегменту билета: (ticket_no, flight_id). У одного билета может быть несколько таких строк. Сборка показана на карте и в разборе SQL. Карту открывайте локально.

Перед запуском

Дождитесь успешных STG и ODS. Таблицы DDS должны быть созданы через bookings_dds_ddl или общий make ddl-gp. Затем в Airflow UI запустите bookings_to_gp_dds целиком. DDS читает состояние ODS; передавать stg_batch_id ему не нужно.

Объект Что уже выполняется на main
dim_calendar Заполнение датами с 2016-01-01 по 2030-12-31, только если таблица пуста
dim_airports Обновление изменившихся атрибутов и вставка новых аэропортов с постоянными SK
dim_tariffs Добавление новых классов обслуживания из ods.segments
fact_flight_sales Обновление существующих сегментов и вставка новых пар (ticket_no, flight_id)
dim_airplanes, dim_passengers, dim_routes Загрузки и DQ пока содержат SELECT 1;; требования находятся в части 2 ТЗ

До выполнения заданий три студенческих измерения остаются пустыми. Готовый факт при этом загружается: отсутствующие ключи измерений сохраняются как NULL, чтобы можно было изучить цепочку до написания собственного SQL.

Порядок задач

В DAG сначала выполняется load_dds_dim_calendar → dq_dds_dim_calendar. Затем:

  1. Параллельно могут загружаться dim_airports, dim_airplanes, dim_tariffs и dim_passengers; у каждого измерения своя следующая DQ-задача.
  2. load_dds_dim_routes ждет dq_dds_dim_airports и dq_dds_dim_airplanes, затем выполняется dq_dds_dim_routes.
  3. load_dds_fact_flight_sales ждет DQ всех пяти измерений после календаря.
  4. dq_dds_fact_flight_sales → finish_dds_summary завершают запуск.

Это порядок задач Airflow. Источники строк и поля соединений показаны на карте отдельно от него.

Как работают готовые загрузки

dim_calendar_load.sql проверяет NOT EXISTS (SELECT 1 FROM dds.dim_calendar LIMIT 1). Если есть хотя бы одна строка, скрипт не вставляет даты. Повторный запуск не пересоздает календарь и не дополняет частично заполненную таблицу. Его DQ проверяет также покрытие дат рейсов ODS.

dim_airports_load.sql сохраняет SK существующего аэропорта, обновляет изменившиеся атрибуты через IS DISTINCT FROM и вставляет новые бизнес-ключи. dim_tariffs_load.sql только добавляет недостающие значения fare_conditions. Метки измененных строк относятся к текущему запуску DDS; календарь не содержит _load_id и _load_ts.

В fact_flight_sales_load.sql есть две операции:

  • UPDATE меняет цену, место, признак посадки и метки загрузки, если эти бизнес-поля изменились. SK измерений остаются прежними.
  • INSERT собирает данные из ODS и измерений для пар (ticket_no, flight_id), которых еще нет в факте.

Факт не отбирает дельту по HWM. Скрипт читает ODS и сопоставляет бизнес-ключи с уже записанными строками.

Аэропорты вылета и прилета находятся через ods.routes → dim_airports. Из ODS выбирается строка с наибольшим validity для route_no; сортировка идет по TEXT, дата рейса в этом отборе не участвует. route_sk определяется отдельно: по дате вылета в полуоткрытом интервале [valid_from, valid_to) измерения dim_routes. Из найденной версии берется код модели для поиска airplane_sk. Разбор соединений показывает, какие строки сохраняет LEFT JOIN и что происходит при отсутствии измерения.

Учебные измерения

Начните с моделей самолетов и пассажиров, затем переходите к версиям маршрута. Поля, hashdiff и алгоритм SCD2 определены в ТЗ.

У маршрута изменение версионируемых атрибутов создает новую строку. Описательные поля из других измерений обновляются только у открытых версий (valid_to IS NULL), без новой версии; закрытые версии сохраняют свои значения. Это правило также записано в алгоритме ТЗ.

После реализации измерений выполните пересчет факта и витрин. Обычный повторный запуск DDS не заполнит SK в старых строках факта, поскольку его UPDATE эти поля не меняет.

Проверка результата

В make gp-psql выполните:

SELECT COUNT(*) FROM dds.dim_calendar;
SELECT COUNT(*) FROM dds.dim_airports;
SELECT COUNT(*) FROM dds.dim_tariffs;

SELECT
    (SELECT COUNT(*) FROM dds.fact_flight_sales) AS fact_rows,
    (SELECT COUNT(*) FROM ods.segments) AS segment_rows;

SELECT ticket_no, flight_id, departure_airport_sk, arrival_airport_sk,
       route_sk, airplane_sk, passenger_sk, price, is_boarded
FROM dds.fact_flight_sales
ORDER BY ticket_no, flight_id
LIMIT 10;

На подготовленном стенде готовые измерения и факт непусты. fact_rows должен точно совпасть с segment_rows. Готовая DQ факта также ищет дубли по паре ключей и проверяет обязательные поля.

На учебной ветке NULL в passenger_sk, route_sk и airplane_sk вызывает только NOTICE. NULL в tariff_sk вызывает ошибку; для строк с отсутствующим аэропортом и для calendar_sk допустима доля не выше 1%. Эти послабления не заменяют проверку заполнения ключей после задания.

Свои *_dq.sql реализуйте по ТЗ и справочнику DQ. Для дополнительной проверки DDS используйте validate_dds в bookings_validate, соблюдая порядок запуска и восстановления. Далее переходите к DM.

Если загрузка не прошла

  • Нет dds.*: выполните bookings_dds_ddl.
  • DQ календаря сообщает о непокрытых датах: сравните даты вылета ODS с диапазоном и содержимым dim_calendar. Повторный запуск загрузки непустого календаря не заполнит пропуски.
  • Число строк факта отличается от ODS: проверьте ключи билета, бронирования и рейса, затем соединения в fact_src. Потеря строки на INNER JOIN и размножение строк из-за нескольких подходящих версий дают разные причины одного расхождения.
  • Ошибка в вашей DQ маршрутов: проверьте открытые версии, интервалы и hashdiff по ТЗ. Успешная заглушка SELECT 1; этих свойств не проверяет.