Files
airflow-greenplum/docs/internal/db_schema.md
T

11 KiB
Raw Blame History

Схема БД DWH (Bookings → Greenplum)

Статус: Проект в разработке. Реализован только STG слой (частично: bookings, tickets).

Обзор

Эта документация описывает архитектуру хранилища данных (DWH) для учебного проекта Airflow + Greenplum. Источник данных — демо-БД bookings (Postgres).

Статус реализации по слоям

Слой Статус Реализовано
Source Готово Демо-БД bookings (Postgres)
STG ⚠️ В процессе 2 из 8 таблиц (bookings, tickets)
DQ ⚠️ В процессе Есть скрипты для bookings и tickets
ODS Не реализован Планируется
DDS Не реализован Планируется

Полная схема потоков данных (Data Lineage)

graph LR
    %% Стили
    classDef source fill:#e1f5fe,stroke:#01579b,stroke-width:2px;
    classDef stg fill:#fff9c4,stroke:#fbc02d,stroke-width:2px;
    classDef dq fill:#ffe0b2,stroke:#ef6c00,stroke-width:2px;
    classDef ods fill:#e0f2f1,stroke:#00695c,stroke-width:2px;
    classDef dim fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px;
    classDef fact fill:#ffccbc,stroke:#bf360c,stroke-width:4px;

    %% 1. Source
    subgraph Source_Postgres [Source: Postgres Bookings]
        direction TB
        SRC_Airports[airports_data]:::source
        SRC_Airplanes[airplanes_data]:::source
        SRC_Seats[seats]:::source
        SRC_Bookings[bookings]:::source
        SRC_Tickets[tickets]:::source
        SRC_Flights[flights]:::source
        SRC_Segments[segments]:::source
        SRC_Boarding[boarding_passes]:::source
    end

    %% 2. STAGING (Load 1-to-1, AO-Row)
    subgraph STG_Layer [Layer: STG Staging]
        direction TB
        STG_Airports[stg.airports]:::stg
        STG_Airplanes[stg.airplanes]:::stg
        STG_Seats[stg.seats]:::stg
        STG_Bookings[stg.bookings]:::stg
        STG_Tickets[stg.tickets]:::stg
        STG_Flights[stg.flights]:::stg
        STG_Segments[stg.segments]:::stg
        STG_Boarding[stg.boarding_passes]:::stg
    end

    %% Links Source to STG
    SRC_Airports --> STG_Airports
    SRC_Airplanes --> STG_Airplanes
    SRC_Seats --> STG_Seats
    SRC_Bookings --> STG_Bookings
    SRC_Tickets --> STG_Tickets
    SRC_Flights --> STG_Flights
    SRC_Segments --> STG_Segments
    SRC_Boarding --> STG_Boarding

    %% 3. DATA QUALITY (Quality Checks)
    subgraph DQ_Layer [Layer: DQ Data Quality]
        direction TB
        DQ_Bookings[dq.bookings_checks]:::dq
        DQ_Tickets[dq.tickets_checks]:::dq
        DQ_Flights[dq.flights_checks]:::dq
        DQ_Segments[dq.segments_checks]:::dq
    end

    %% Links STG to DQ
    STG_Bookings --> DQ_Bookings
    STG_Tickets --> DQ_Tickets
    STG_Flights --> DQ_Flights
    STG_Segments --> DQ_Segments

    %% 4. ODS (3NF, Clean, Type, Heap)
    subgraph ODS_Layer [Layer: ODS Operational Core]
        direction TB
        ODS_Airports[ods.airports]:::ods
        ODS_Airplanes[ods.airplanes]:::ods
        ODS_Seats[ods.seats]:::ods
        ODS_Bookings[ods.bookings]:::ods
        ODS_Tickets[ods.tickets]:::ods
        ODS_Flights[ods.flights]:::ods
        ODS_Segments[ods.segments]:::ods
        ODS_Boarding[ods.boarding_passes]:::ods
    end

    %% Links DQ to ODS
    DQ_Bookings --> ODS_Bookings
    DQ_Tickets --> ODS_Tickets
    DQ_Flights --> ODS_Flights
    DQ_Segments --> ODS_Segments
    STG_Airports --> ODS_Airports
    STG_Airplanes --> ODS_Airplanes
    STG_Seats --> ODS_Seats
    STG_Boarding --> ODS_Boarding

    %% 5. DDS (Star Schema)
    subgraph DDS_Layer [Layer: DDS Star Schema]
        direction TB
        
        %% Dimensions
        DIM_Calendar[dim.calendar]:::dim
        DIM_Airports[dim.airports]:::dim
        DIM_Airplanes[dim.airplanes]:::dim
        DIM_Tariffs[dim.tariffs]:::dim
        DIM_Passengers[dim.passengers]:::dim

        %% Fact
        FACT_Sales[fact.flight_sales]:::fact
    end

    %% Transformations ODS to DDS

    %% Form reference tables
    ODS_Airports --> DIM_Airports
    
    ODS_Airplanes --> DIM_Airplanes
    ODS_Seats -.->|Enrich total_seats| DIM_Airplanes
    
    ODS_Segments -.->|Extract distinct| DIM_Tariffs
    
    ODS_Tickets -->|Extract Unique| DIM_Passengers

    %% Fact assembly (Main process)
    ODS_Segments -->|Main Stream| FACT_Sales
    ODS_Tickets -->|Join book_ref passenger_id| FACT_Sales
    ODS_Flights -->|Join Times Status| FACT_Sales
    ODS_Boarding -->|LEFT JOIN Seat No| FACT_Sales
    
    %% Link dimensions to fact
    DIM_Calendar -->|calendar_sk| FACT_Sales
    DIM_Airports -->|departure_airport_sk| FACT_Sales
    DIM_Airports -->|arrival_airport_sk| FACT_Sales
    DIM_Airplanes -->|airplane_sk| FACT_Sales
    DIM_Tariffs -->|tariff_sk| FACT_Sales
    DIM_Passengers -->|passenger_sk| FACT_Sales

Пояснения к схеме (для студентов)

Эта диаграмма покрывает 100% таблиц источника и показывает логику их трансформации. Вот на что стоит обратить внимание при обучении:

1. Ветка справочников (Reference Data)

  • seats + airplanesdim.airplanes: Здесь мы показываем пример обогащения. Таблица seats сама по себе в аналитике редко нужна отдельной сущностью. Мы используем её в ODS, чтобы посчитать общее количество мест (total_seats) и добавить это как атрибут в измерение самолётов (dim.airplanes).

  • airportsdim.airports: Простой перенос (1-в-1), но в DDS мы можем добавить, например, поле city_ru и city_en как отдельные колонки, убрав JSON, который есть в источнике.

2. Ветка генерации измерений (Dimension Generation)

  • ticketsdim.passengers: Это самая сложная трансформация для измерения. В источнике нет таблицы "Пассажиры". Мы должны объяснить студентам, что мы "майним" пассажиров из билетов. Важно: один и тот же пассажир может иметь разные записи с разными именами (опечатки, изменение фамилии), поэтому нужна логика SCD Type 2 для отслеживания изменений.

  • segmentsdim.tariffs: Таблицы тарифов физически нет в источнике, она "зашита" строкой (Economy, Business) в таблице полётов. Мы выносим её в отдельный справочник (Нормализация), чтобы в факте хранить маленький INT ключ, а не длинную строку.

3. Сборка Факта (fact.flight_sales)

Это центр звезды. Мы собираем его из четырёх ODS таблиц:

  1. ods.segments: Основа (зерно факта — один полётный сегмент билета). Дает сумму (amount).
  2. ods.tickets: Приджойниваем, чтобы получить book_ref и passenger_id.
  3. ods.flights: Приджойниваем, чтобы получить точное время вылета/прилета (для FK на календарь) и статусы.
  4. ods.boarding_passes: Приджойниваем (LEFT JOIN), чтобы узнать, сел ли пассажир реально в самолёт и на какое место (seat_no). Это важный бизнес-аспект: билет куплен, но посадочный не выдан = пассажир не летел.

4. Почему нет dim.bookings?

В классической Star Schema измерения — это справочники (airports, aircrafts, passengers), а факты — транзакции/события (sales, bookings).

bookings — это транзакционная таблица, а не справочник. Вместо отдельного измерения dim.bookings мы храним:

  • book_ref — бизнес-ключ бронирования (в факте)
  • book_date — дата бронирования (в факте)

Это позволяет отвечать на вопросы типа: "За сколько дней до вылета люди обычно покупают билеты?" (разница между book_date и датой вылета из dim.calendar).

5. Суррогатные ключи (Surrogate Keys)

В Star Schema факт должен ссылаться на суррогатные ключи (SK) измерений, а не на бизнес-ключи:

Бизнес-ключ Суррогатный ключ Преимущество
airport_code CHAR(3) airport_sk INT Меньший размер, стабильность
airplane_code TEXT airplane_sk INT Меньший размер, стабильность
passenger_id TEXT passenger_sk INT Меньший размер, отслеживание изменений

6. Слой DQ (Data Quality)

Между STG и ODS добавлен слой Data Quality для проверки качества данных. В проекте уже есть скрипты:

  • sql/stg/bookings_dq.sql
  • sql/stg/tickets_dq.sql

На схеме показаны примеры проверок для всех таблиц, которые должны быть реализованы.


История изменений

Дата Версия Описание изменений
2025-01-17 1.1 Исправлены названия таблиц (aircrafts_dataairplanes_data, ticket_flightssegments), удалено dim.bookings, добавлены суррогатные ключи, добавлен слой DQ, исправлены связи
2025-01-XX 1.0 Первоначальная версия

TODO

  • Реализовать STG слой полностью (все 8 таблиц)
  • Реализовать DQ слой для всех таблиц
  • Реализовать ODS слой
  • Реализовать DDS слой (измерения и факт)
  • Создать DAG для загрузки ODS
  • Создать DAG для загрузки DDS