Merge branch 'docs/main-docs'
This commit is contained in:
@@ -66,7 +66,7 @@
|
||||
|
||||
## Безопасность и конфигурация
|
||||
- Все настройки — через `.env`; креды в коде не хардкодим. Частые переменные: `GP_*`, `PG_*`, `AIRFLOW_*`, `CSV_*`.
|
||||
- `make down` удаляет тома — предупреждайте студентов, что данные пропадут.
|
||||
- `make clean` удаляет тома — предупреждайте студентов, что данные пропадут.
|
||||
|
||||
## Для агента (особенности аудитории)
|
||||
- Пишите простыми словами. Добавляйте короткие комментарии к нетривиальной логике.
|
||||
|
||||
@@ -1,493 +1,140 @@
|
||||
# airflow-dwh-gp-lab
|
||||
# airflow-dwh-gp-lab
|
||||
|
||||
Учебный стенд: ETL из Postgres в Greenplum с оркестрацией в Airflow.
|
||||
Учебный стенд для лабораторных по Data Engineering: **Airflow** оркестрирует загрузку данных из демо‑БД
|
||||
**bookings** (Postgres) в **Greenplum**.
|
||||
|
||||
Добро пожаловать в учебный стенд для изучения основ Data Engineering! Этот проект поможет вам освоить ключевые инструменты современных data pipeline: **Airflow** для оркестрации, **pandas/CSV** для подготовки данных, **Postgres** с демобазой **bookings** как источник и **Greenplum** как аналитическую базу данных.
|
||||
## Зачем этот стенд
|
||||
|
||||
Если вы проходите стенд как серию лабораторных, смотрите также файл с заданиями: `educational-tasks.md`.
|
||||
Основная цель стенда — дать вам удобное место для лабораторных работ и будущей курсовой:
|
||||
вы построите небольшое аналитическое хранилище данных (DWH) на базе **Greenplum** и закрепите навыки:
|
||||
|
||||
## 🎯 Что вы узнаете
|
||||
- моделирования данных (слои DWH, модели, витрины);
|
||||
- построения ETL/ELT;
|
||||
- работы с Airflow и Greenplum.
|
||||
|
||||
- Как настроить локальный стек данных с помощью Docker
|
||||
- Как Airflow управляет workflow и координирует задачи
|
||||
- Как генерировать датасеты через pandas и сохранять их в CSV
|
||||
- Как загружать данные в Greenplum пакетами и избегать дублей
|
||||
- Как проверять качество данных в автоматизированных pipeline
|
||||
- Основы проектирования ETL/ELT процессов
|
||||
- Как работать с демо-БД bookings в Postgres как источником для будущего DWH
|
||||
В курсовой у нас один источник данных — демо‑БД **bookings**. В стенде уже есть готовый учебный пример
|
||||
загрузки **bookings → stg в Greenplum**, чтобы вы могли сфокусироваться на DWH‑части (ODS/DDS/DM) и
|
||||
не тратить время на инфраструктуру.
|
||||
|
||||
## 👩🎓 Для студентов (10‑минутный чек‑лист)
|
||||
## Что внутри
|
||||
|
||||
- Установите Docker Desktop и Git.
|
||||
- Скопируйте настройки: `cp .env.example .env`.
|
||||
- Поднимите стенд: `make up` (или `docker compose up -d` — сервис `airflow-init` запустится автоматически при первом старте).
|
||||
- Откройте UI: http://localhost:8080 (admin/admin).
|
||||
- Включите и запустите DAG `csv_to_greenplum`. Дождитесь Success.
|
||||
- Проверьте данные: `make gp-psql` → `SELECT COUNT(*) FROM public.orders;`.
|
||||
- Дополнительно: запустите `csv_to_greenplum_dq` — все проверки должны быть зелёные.
|
||||
- **Airflow** (UI: http://localhost:8080, логин/пароль: admin/admin)
|
||||
- **Greenplum** (single‑node для обучения; внешний порт по умолчанию `5435`)
|
||||
- **bookings-db** (Postgres с демо‑БД `demo`; внешний порт по умолчанию `5434`)
|
||||
- **PXF** как “транспорт” между Postgres и Greenplum (уже настроен в образе)
|
||||
- Побочный пример: загрузка данных через **pandas/CSV** (`csv_to_greenplum`)
|
||||
|
||||
Если что‑то не работает — смотрите «Типичные проблемы» и «Быстрый reset» ниже.
|
||||
## PXF (в 5 строк)
|
||||
|
||||
## 🚀 Быстрый старт (для новичков)
|
||||
PXF (Platform Extension Framework) — компонент Greenplum для работы с внешними источниками.
|
||||
В этом стенде PXF используется для чтения таблицы `bookings.bookings` из Postgres прямо из Greenplum
|
||||
через внешнюю таблицу `stg.bookings_ext`. Поэтому загрузка в `stg.bookings` выглядит как обычный
|
||||
`INSERT ... SELECT` без промежуточных CSV.
|
||||
Подробное руководство по PXF смотрите в официальной документации Greenplum.
|
||||
|
||||
### Шаг 1: Подготовка окружения
|
||||
## Быстрый старт (основной сценарий: bookings → stg)
|
||||
|
||||
**Требования:**
|
||||
- Docker Desktop (Windows/Mac) или Docker Engine 24+ (Linux)
|
||||
- Git для клонирования репозитория
|
||||
|
||||
> 💡 **Совет:** Если у вас Windows, рекомендуем использовать WSL (Windows Subsystem for Linux) для лучшей совместимости.
|
||||
|
||||
### Шаг 2: Настройка проекта
|
||||
1) Скопируйте настройки:
|
||||
|
||||
```bash
|
||||
# Скопируйте файл настроек
|
||||
cp .env.example .env
|
||||
|
||||
# Запустите стек (это может занять 2-3 минуты при первом запуске)
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Шаг 3: Первый запуск pipeline
|
||||
|
||||
1. Откройте Airflow UI: **http://localhost:8080** (логин/пароль: admin/admin)
|
||||
2. Найдите DAG с названием **csv_to_greenplum**
|
||||
3. Нажмите на переключатель слева от названия DAG, чтобы включить его
|
||||
4. Нажмите кнопку **Trigger** (значок воспроизведения ▶️)
|
||||
|
||||
🎉 **Поздравляем!** Вы только что запустили свой первый data pipeline:
|
||||
- Система сгенерировала 1000 тестовых заказов при помощи pandas
|
||||
- Датасет сохранился в CSV-файл в каталоге `./data`
|
||||
- Airflow загрузил данные из CSV в Greenplum без дублей по `order_id`
|
||||
|
||||
### Шаг 4: Проверка результатов
|
||||
|
||||
**Проверка вручную:**
|
||||
```bash
|
||||
# Подключитесь к Greenplum и проверьте данные
|
||||
docker compose exec greenplum bash -c "su - gpadmin -c 'psql -p 5432 -d gp_dwh'"
|
||||
|
||||
# Внутри psql выполните:
|
||||
\dt # Показать таблицы
|
||||
SELECT count(*) FROM public.orders; # Посчитать записи
|
||||
|
||||
# Посмотреть несколько строк
|
||||
SELECT * FROM public.orders LIMIT 5;
|
||||
```
|
||||
|
||||
CSV-файлы после выполнения DAG остаются в директории `./data`. Их можно открыть любым редактором или изучить через pandas.
|
||||
|
||||
### Быстрый reset
|
||||
|
||||
Если после изменений что‑то «сломалось»:
|
||||
2) Поднимите стенд:
|
||||
|
||||
```bash
|
||||
make down # Остановить и удалить контейнеры/сети (volumes сохраняются)
|
||||
make up
|
||||
# если make не установлен: docker compose up -d
|
||||
```
|
||||
|
||||
Если проблема связана с «грязной» остановкой и данными в томах (например, Greenplum не стартует),
|
||||
используйте полный reset: `make clean && make up` (данные в Docker-томах будут потеряны).
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Подробная настройка (для уверенных пользователей)
|
||||
|
||||
> Если вы впервые запускаете стенд, этот раздел можно пролистать и вернуться к нему позже.
|
||||
|
||||
### Установка Make (опционально)
|
||||
|
||||
Для удобства работы с проектом рекомендуем установить `make`:
|
||||
|
||||
- **Linux (Debian/Ubuntu):** `sudo apt install -y make`
|
||||
- **macOS:** `brew install make`
|
||||
- **Windows:**
|
||||
- WSL: `sudo apt install -y make`
|
||||
- Chocolatey: `choco install make`
|
||||
- Scoop: `scoop install make`
|
||||
|
||||
С `make` команды становятся короче:
|
||||
```bash
|
||||
make up # Запуск стека (включая airflow-init при первом старте)
|
||||
make logs # Просмотр логов
|
||||
make gp-psql # Подключение к Greenplum
|
||||
```
|
||||
|
||||
### Настройка подключения к Greenplum в Airflow
|
||||
|
||||
По умолчанию готовые DAG используют Airflow Connections. В docker-compose они
|
||||
заводятся автоматически через переменные окружения:
|
||||
|
||||
- `AIRFLOW_CONN_GREENPLUM_CONN` — подключение к Greenplum с `conn_id=greenplum_conn`;
|
||||
- `AIRFLOW_CONN_BOOKINGS_DB` — подключение к демо-БД bookings с `conn_id=bookings_db`.
|
||||
|
||||
Такие подключения подхватываются из окружения и могут не отображаться в UI,
|
||||
но для DAG это нормально — `PostgresOperator` найдёт их по `conn_id`.
|
||||
|
||||
При желании вы можете создать или отредактировать подключение вручную в UI:
|
||||
|
||||
1. Airflow UI → **Admin → Connections → Add a new record**
|
||||
2. Заполните поля:
|
||||
- **Conn Id:** `greenplum_conn`
|
||||
- **Conn Type:** `Postgres`
|
||||
- **Host:** `greenplum`
|
||||
- **Schema:** `gp_dwh`
|
||||
- **Login:** `gpadmin`
|
||||
- **Password:** `gpadmin`
|
||||
- **Port:** `5432`
|
||||
|
||||
---
|
||||
|
||||
### Greenplum + PXF: свой образ
|
||||
|
||||
Чтобы избежать проблем с правами и нестабильных запусков, Greenplum собирается
|
||||
из собственного `Dockerfile.greenplum`. В образ вшиты:
|
||||
|
||||
- JDBC-драйвер PostgreSQL;
|
||||
- конфигурация PXF-сервера `bookings-db`;
|
||||
- ensure-скрипт, который при каждом старте контейнера докладывает файлы в `PXF_BASE`.
|
||||
|
||||
Дополнительно при старте контейнера:
|
||||
|
||||
- базовые конфиги PXF копируются в `PXF_BASE/conf` (если их ещё нет);
|
||||
- создаются каталоги `PXF_BASE/run` и `PXF_BASE/logs`;
|
||||
- `CREATE EXTENSION pxf` выполняется автоматически, когда Greenplum становится доступен (с ретраями).
|
||||
|
||||
Healthcheck сервиса `greenplum` учитывает не только готовность Greenplum, но и запуск PXF,
|
||||
а также наличие `extension pxf` — это нужно, чтобы Airflow не стартовал раньше PXF.
|
||||
|
||||
Сборка и запуск:
|
||||
|
||||
- `make build` — собрать образ (явно);
|
||||
- `make up` — поднимет стек и соберёт образ, если он ещё не создан.
|
||||
|
||||
Обновление PXF-конфигов:
|
||||
|
||||
- изменили файлы в `pxf/` → выполните `make build` и перезапустите контейнер;
|
||||
- для принудительной перезаписи файлов в `PXF_BASE` используйте `PXF_SEED_OVERWRITE=1`;
|
||||
- для принудительного `pxf cluster sync` при старте используйте `PXF_SYNC_ON_START=1`.
|
||||
|
||||
Проверка PXF:
|
||||
|
||||
- статус: `docker compose exec greenplum bash -lc "su - gpadmin -c '/usr/local/pxf/bin/pxf cluster status'"`;
|
||||
- логи: `greenplum_data:/data/pxf/logs` (внутри контейнера — `/data/pxf/logs`).
|
||||
|
||||
---
|
||||
|
||||
### Airflow: свой образ
|
||||
|
||||
Airflow тоже собирается из собственного `Dockerfile.airflow`, чтобы зависимости ставились при сборке, а не во время старта контейнеров. В образ включены:
|
||||
|
||||
- Python‑зависимости из `airflow/requirements.txt`;
|
||||
- утилита `psql` для быстрых проверок внутри контейнера.
|
||||
|
||||
Если меняли `airflow/requirements.txt` или `Dockerfile.airflow`, пересоберите образы: `make build`, затем `make up`.
|
||||
|
||||
В docker-compose по умолчанию задан `AIRFLOW__CORE__EXECUTOR=LocalExecutor` (параллельное выполнение задач). Если нужен последовательный режим — замените на `SequentialExecutor` в `docker-compose.yml`.
|
||||
|
||||
---
|
||||
|
||||
### Локальное окружение разработчика
|
||||
|
||||
Локальным окружением управляет [uv](https://docs.astral.sh/uv/) — он скачивает нужный Python и создаёт `.venv` на основе `pyproject.toml` / `uv.lock`.
|
||||
3) Инициализируйте демо‑БД bookings:
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
make bookings-init
|
||||
```
|
||||
|
||||
`uv sync` сам подтянет версию Python из `.python-version`/`pyproject.toml`, создаст `.venv` и установит зависимости. Для тех же действий можно использовать `make dev-sync`. Цель `make dev-setup` (или вручную `uv python install` + `uv python pin`) нужна только когда вы меняете версию Python или прогреваете кэш.
|
||||
4) Подготовьте STG‑объекты в Greenplum (выберите один вариант):
|
||||
|
||||
> Если требуется «классическое» активированное окружение, после `uv sync` выполните `.\.venv\Scripts\Activate.ps1` в PowerShell или `source .venv/bin/activate` в Unix-терминале.
|
||||
- Учебный вариант: в Airflow UI запустите DAG `bookings_stg_ddl`;
|
||||
- Технический шорткат: `make ddl-gp` (применяет все DDL разом вручную).
|
||||
|
||||
Проверки и форматирование выполняем через uv:
|
||||
5) Запустите основной DAG `bookings_to_gp_stage`.
|
||||
|
||||
6) Проверьте результат в Greenplum:
|
||||
|
||||
```bash
|
||||
make test # uv run pytest -q
|
||||
make lint # black/isort в режиме проверки
|
||||
make fmt # автоформатирование black + isort
|
||||
make gp-psql
|
||||
-- внутри psql:
|
||||
SELECT COUNT(*) FROM stg.bookings;
|
||||
SELECT * FROM stg.bookings ORDER BY src_created_at_ts DESC LIMIT 10;
|
||||
```
|
||||
|
||||
#### Быстрый старт с uv
|
||||
Подробнее про логику DAG и проверки — `docs/bookings_to_gp_stage.md`.
|
||||
|
||||
## DAG-и в стенде
|
||||
|
||||
Основные (для потока bookings → DWH):
|
||||
|
||||
- `bookings_stg_ddl` — создаёт `stg.bookings_ext` и `stg.bookings` в Greenplum;
|
||||
- `bookings_to_gp_stage` — генерирует учебный день в `bookings-db` и грузит инкремент в `stg.bookings`
|
||||
(через PXF), затем выполняет DQ‑проверку.
|
||||
|
||||
Вспомогательные (побочный трек с CSV):
|
||||
|
||||
- `orders_base_ddl` — создаёт таблицу `public.orders` для CSV‑пайплайна;
|
||||
- `csv_to_greenplum` — pandas → CSV → Greenplum (пример загрузки без источника‑БД);
|
||||
- `csv_to_greenplum_dq` — проверки качества данных для `public.orders`.
|
||||
|
||||
## Полезные команды
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
uv run pytest -q
|
||||
uv run black --check airflow tests
|
||||
make up # поднять стек
|
||||
make logs # логи airflow-webserver и airflow-scheduler
|
||||
make gp-psql # psql в Greenplum
|
||||
make bookings-psql # psql в демо-БД bookings (Postgres)
|
||||
make ddl-gp # применить DDL к Greenplum вручную (вместо DDL-DAG)
|
||||
make down # остановить и удалить контейнеры/сети (volumes сохраняются)
|
||||
make clean # полный reset: удалить контейнеры/сети и volumes (данные будут потеряны)
|
||||
```
|
||||
|
||||
> Не устанавливайте пакеты напрямую через `pip install --user ...`. Если что-то уже попало в user-site, удалите `pip uninstall <package>` и проверьте `pip list --user`.
|
||||
---
|
||||
## Подключение через DBeaver (опционально)
|
||||
|
||||
|
||||
## 📋 Что входит в стенд
|
||||
|
||||
### Основные компоненты
|
||||
- **Greenplum** — аналитическая база данных для хранения и анализа данных
|
||||
- **Airflow** — оркестратор workflow и задач
|
||||
- **Postgres** — база метаданных для Airflow
|
||||
- **Postgres (bookings)** — отдельная демо-БД bookings (источник данных для будущего DWH в Greenplum)
|
||||
- **pandas** — библиотека для генерации и анализа данных в формате CSV
|
||||
|
||||
### Готовые DAG (workflow)
|
||||
- **orders_base_ddl** — создаёт базовую таблицу `public.orders` для CSV‑пайплайна
|
||||
- **bookings_stg_ddl** — готовит схему `stg` и таблицы `stg.bookings_ext` / `stg.bookings`
|
||||
- **csv_to_greenplum** — базовый pipeline: pandas → CSV → Greenplum
|
||||
- **bookings_to_gp_stage** — пример загрузки из демо‑БД bookings в слой STG
|
||||
- **csv_to_greenplum_dq** — проверки качества данных (наличие таблицы, схема, дубликаты)
|
||||
|
||||
> Учебный путь — триггернуть DDL‑DAG: для CSV `orders_base_ddl`, для bookings `bookings_stg_ddl`. Технический шорткат для быстрой инициализации — `make ddl-gp` (он не вызывается автоматически при старте контейнеров).
|
||||
|
||||
### Полезные команды
|
||||
```bash
|
||||
# Основные команды
|
||||
make up # Запустить весь стенд (Airflow инициализируется автоматически при первом старте)
|
||||
make stop # Остановить контейнеры, не трогая данные
|
||||
make down # Остановить и удалить контейнеры/сети (volumes сохраняются)
|
||||
make clean # Полный reset: остановить и удалить контейнеры/сети и тома (данные будут потеряны)
|
||||
make airflow-init # Ручной запуск инициализации Airflow (обычно не нужен)
|
||||
make ddl-gp # Применить DDL к Greenplum вручную
|
||||
make gp-psql # Подключиться к Greenplum через psql
|
||||
make bookings-init # Установить демобазу bookings в Postgres (по умолчанию генерирует 1 день)
|
||||
make bookings-generate-day # Добавить ещё один день данных в bookings (можно вызвать несколько раз)
|
||||
make bookings-psql # Подключиться к демобазе bookings (БД demo)
|
||||
|
||||
# Проверка данных
|
||||
make logs # Следить за логами Airflow
|
||||
|
||||
# Логи задач Airflow сохраняются в Docker-томе `airflow_logs`
|
||||
# и переживают `docker compose down`/`up` (удаляются при `docker compose down -v` / `make clean`).
|
||||
|
||||
# Контроль генерации bookings
|
||||
docker compose -f docker-compose.yml exec bookings-db bash -lc 'PGPASSWORD="$POSTGRES_PASSWORD" psql -U "$POSTGRES_USER" -d demo -c "SELECT busy();"'
|
||||
# busy() = t — генерация ещё идёт; f — завершена. При необходимости можно вызвать CALL abort(); и запустить генерацию заново.
|
||||
```
|
||||
|
||||
### Генерация следующего дня в bookings
|
||||
|
||||
- При `make bookings-init` автоматически генерируется `BOOKINGS_INIT_DAYS` суток, начиная с даты `BOOKINGS_START_DATE` (по умолчанию один день с `2017-01-01`).
|
||||
- Дальше каждый вызов `make bookings-generate-day` или генерации через DAG добавляет ровно **один** следующий день после `max(book_date)` в `bookings.bookings` — генератор сам смотрит последнюю дату.
|
||||
- Рекомендуемый учебный сценарий для DAG `bookings_to_gp_stage`: запускать DAG по одному дню вперёд, выбирая в форме Trigger логическую дату `Execution Date (ds)`, совпадающую с тем днём, который вы хотите загрузить (например, `2017-01-01`, затем `2017-01-02` и т.д.).
|
||||
|
||||
- Быстрее всего: `make bookings-generate-day` — читает GUC и сам вызывает `continue`.
|
||||
- Вручную из psql/DBeaver (подзапросы в аргументах CALL не работают, поэтому через DO-блок):
|
||||
```sql
|
||||
DO $$
|
||||
DECLARE
|
||||
v_next_day timestamptz;
|
||||
BEGIN
|
||||
SELECT date_trunc('day', max(book_date)) + interval '1 day'
|
||||
INTO v_next_day
|
||||
FROM bookings.bookings;
|
||||
CALL continue(v_next_day); -- или CALL continue(v_next_day, 4) для параллельности
|
||||
END $$;
|
||||
```
|
||||
- Не вызывайте `CALL generate(...)` поверх существующих данных: она делает TRUNCATE и создаёт демобазу заново.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Настройка через переменные окружения
|
||||
|
||||
Все настройки находятся в файле `.env`. Основные параметры:
|
||||
Перед подключением убедитесь, что стенд поднят (`make up`).
|
||||
|
||||
### Greenplum
|
||||
- `GP_USER` — пользователь (по умолчанию: gpadmin)
|
||||
- `GP_PASSWORD` — пароль (по умолчанию: gpadmin)
|
||||
- `GP_DB` — база данных (по умолчанию: gp_dwh)
|
||||
- `GP_PORT` — порт Greenplum внутри Docker-сети (по умолчанию: 5432, менять обычно не нужно; внешний порт на хосте для подключения клиентов — 5435).
|
||||
|
||||
### Демо-БД bookings (Postgres)
|
||||
- `BOOKINGS_DB_USER` — пользователь Postgres для демобазы (по умолчанию: bookings)
|
||||
- `BOOKINGS_DB_PASSWORD` — пароль пользователя (по умолчанию: bookings)
|
||||
- `BOOKINGS_DB_NAME` — база данных, из которой запускается установка генератора (по умолчанию: bookings)
|
||||
- `BOOKINGS_DB_PORT` — внешний порт для подключения к контейнеру bookings-db (по умолчанию: 5434)
|
||||
- `BOOKINGS_START_DATE` — начальная дата модельного времени (по умолчанию: 2017-01-01)
|
||||
- `BOOKINGS_INIT_DAYS` — сколько дней сгенерировать при первой инициализации (по умолчанию: 1, чтобы увидеть данные без долгого ожидания; можно менять при вызове `BOOKINGS_INIT_DAYS=... make bookings-init`)
|
||||
- `BOOKINGS_JOBS` — число параллельных джобов генератора bookings (по умолчанию: 1; при 1 генерация идёт синхронно без dblink)
|
||||
- `Host`: `localhost`
|
||||
- `Port`: `5435`
|
||||
- `Database`: значение `GP_DB` из `.env` (по умолчанию `gp_dwh`)
|
||||
- `Username`: значение `GP_USER` (по умолчанию `gpadmin`)
|
||||
- `Password`: значение `GP_PASSWORD` (по умолчанию `gpadmin`)
|
||||
|
||||
### CSV pipeline
|
||||
- `CSV_DIR` — путь к каталогу с CSV внутри контейнеров Airflow (по умолчанию: `/opt/airflow/data`)
|
||||
- `CSV_ROWS` — количество строк, генерируемых DAG (по умолчанию: 1000)
|
||||
### bookings-db (Postgres, демо-БД `demo`)
|
||||
|
||||
### Airflow
|
||||
- `GP_CONN_ID` — ID подключения (по умолчанию: greenplum_conn)
|
||||
- `Host`: `localhost`
|
||||
- `Port`: значение `BOOKINGS_DB_PORT` из `.env` (по умолчанию `5434`)
|
||||
- `Database`: `demo`
|
||||
- `Username`: значение `BOOKINGS_DB_USER` (по умолчанию `bookings`)
|
||||
- `Password`: значение `BOOKINGS_DB_PASSWORD` (по умолчанию `bookings`)
|
||||
|
||||
---
|
||||
## Документация
|
||||
|
||||
## 🔍 Продвинутые темы
|
||||
- Учебные задания: `educational-tasks.md`).
|
||||
- План тестирования/проверок и негативные кейсы: `TESTING.md`.
|
||||
- Дополнительные заметки и технические детали: `docs/README.md`.
|
||||
|
||||
> Этот раздел не обязателен при первом прохождении стенда; к нему удобно вернуться, когда базовый CSV‑pipeline уже понятен.
|
||||
|
||||
### Архитектура pipeline
|
||||
|
||||
**Поток данных в DAG `csv_to_greenplum`:**
|
||||
1. `create_orders_table` — создаёт таблицу `public.orders` в Greenplum
|
||||
2. `generate_csv` — генерирует датасет при помощи pandas и сохраняет CSV в `CSV_DIR`
|
||||
3. `preview_csv` — выводит предпросмотр и статистику по данным
|
||||
4. `load_csv_to_greenplum` — загружает CSV во временную таблицу и переносит новые строки в `public.orders`
|
||||
|
||||
> 💡 **Безопасность повторного запуска:** Pipeline защищен от дубликатов, поэтому его можно запускать многократно.
|
||||
|
||||
### Проверка качества данных
|
||||
|
||||
Запустите DAG `csv_to_greenplum_dq` для автоматической проверки:
|
||||
- Наличие таблицы в базе
|
||||
- Соответствие схемы ожидаемой структуре
|
||||
- Объем загруженных данных
|
||||
- Отсутствие дубликатов записей
|
||||
|
||||
### Пример DAG с SQL-скриптами (bookings → stg)
|
||||
|
||||
> Если вы ещё не дошли до части про bookings и слои DWH, этот подраздел можно пропустить на первом чтении.
|
||||
|
||||
В репозитории есть учебный DAG `bookings_to_gp_stage`, который показывает «канонический» способ работы с SQL в Airflow:
|
||||
|
||||
- подключение к БД через Airflow Connections (`bookings_db`, `greenplum_conn`);
|
||||
- бизнес-логика инкрементальной загрузки и DQ вынесена в SQL-файлы в каталоге `sql/`:
|
||||
- `sql/src/bookings_generate_day_if_missing.sql` — генерация следующего учебного дня в демо-БД bookings (или нескольких стартовых дней, если база пуста);
|
||||
- `sql/stg/bookings_ddl.sql` — DDL для схемы `stg` и таблиц `stg.bookings_ext` / `stg.bookings`;
|
||||
- `sql/stg/bookings_load.sql` — загрузка инкремента из `stg.bookings_ext` в `stg.bookings` на основе «хвоста» после предыдущих батчей;
|
||||
- `sql/stg/bookings_dq.sql` — проверка количества строк между источником и stg за то же окно.
|
||||
|
||||
Фрагмент DAG:
|
||||
|
||||
```python
|
||||
load_bookings_to_stg = PostgresOperator(
|
||||
task_id="load_bookings_to_stg",
|
||||
postgres_conn_id="greenplum_conn",
|
||||
sql="stg/bookings_load.sql",
|
||||
params={"batch_id": "{{ run_id }}"},
|
||||
)
|
||||
```
|
||||
|
||||
Такой подход помогает держать оркестрацию (DAG) и SQL-логику в отдельных файлах и легче сравнивать её с теорией из статьи про моделирование DWH.
|
||||
|
||||
### Ограничения учебного стенда
|
||||
|
||||
- **Greenplum** запущен в single-node режиме (для обучения)
|
||||
- В продакшене Greenplum обычно разворачивают кластером на нескольких серверах
|
||||
- Используется Greenplum 6 (широко доступная версия), хотя Greenplum 7 предлагает больше возможностей
|
||||
|
||||
---
|
||||
|
||||
## 🧩 Подключение к базам через DBeaver
|
||||
|
||||
> Необязательный раздел: нужен только если вы хотите смотреть данные через DBeaver. Для базовых заданий достаточно `make gp-psql`.
|
||||
|
||||
Ниже — краткая инструкция, как подключиться к Greenplum и демо-БД bookings из DBeaver. Перед этим убедитесь, что стенд запущен:
|
||||
|
||||
- `cp .env.example .env` (если ещё не делали)
|
||||
- `make up`
|
||||
- `make bookings-init`
|
||||
- `make ddl-gp`
|
||||
|
||||
### Greenplum (аналитическая БД)
|
||||
|
||||
1. Откройте DBeaver → **New Database Connection**.
|
||||
2. Выберите драйвер **PostgreSQL** (или **Greenplum**, если он есть в вашей версии DBeaver).
|
||||
3. На вкладке **Main** заполните поля (по умолчанию):
|
||||
- `Host`: `localhost`
|
||||
- `Port`: `5435` (внешний порт Greenplum на хосте)
|
||||
- `Database`: значение `GP_DB` (по умолчанию `gp_dwh`)
|
||||
- `Username`: значение `GP_USER` (по умолчанию `gpadmin`)
|
||||
- `Password`: значение `GP_PASSWORD` (по умолчанию `gpadmin`)
|
||||
4. Нажмите **Test Connection** → **OK**, затем **Finish**.
|
||||
|
||||
После подключения:
|
||||
|
||||
- Основные таблицы лаба — в схеме `public` базы `gp_dwh` (например, `public.orders`).
|
||||
- После настройки PXF и выполнения `make ddl-gp` станет доступна внешняя таблица `public.ext_bookings_bookings` — чтение из демо-БД bookings через PXF.
|
||||
|
||||
### bookings-db (демо-БД источника)
|
||||
|
||||
Для работы с исходными данными (демо-БД `demo`) достаточно стандартного PostgreSQL-подключения.
|
||||
|
||||
1. Откройте DBeaver → **New Database Connection** → драйвер **PostgreSQL**.
|
||||
2. На вкладке **Main** укажите (значения по умолчанию из `.env.example`):
|
||||
- `Host`: `localhost`
|
||||
- `Port`: значение `BOOKINGS_DB_PORT` из `.env` (по умолчанию `5434`)
|
||||
- `Database`: `demo`
|
||||
- `Username`: `BOOKINGS_DB_USER` (по умолчанию `bookings`)
|
||||
- `Password`: `BOOKINGS_DB_PASSWORD` (по умолчанию `bookings`)
|
||||
3. Нажмите **Test Connection** → **OK**, затем **Finish**.
|
||||
|
||||
После подключения:
|
||||
|
||||
- Основные таблицы находятся в схеме `bookings` базы `demo` (например, `bookings.bookings`, `bookings.tickets`, `bookings.flights` и т.д.).
|
||||
- Можно сравнивать данные:
|
||||
- между `bookings.bookings` в Postgres и `public.ext_bookings_bookings` в Greenplum;
|
||||
- между временем (`book_date`) в UTC в `demo` и локальным временем в Greenplum (учитывая `TZ=Europe/Moscow`).
|
||||
|
||||
> Если вы меняли порты или креды в `.env`, не забудьте подставить те же значения в настройках соединений в DBeaver.
|
||||
|
||||
---
|
||||
|
||||
## 🆘 Типичные проблемы и решения
|
||||
## Типичные проблемы и решения
|
||||
|
||||
| Проблема | Решение |
|
||||
|----------|---------|
|
||||
| Airflow UI не открывается | Дождитесь сообщения `Listening at: http://0.0.0.0:8080` в логах (`make logs`) |
|
||||
| `database "demo" does not exist` в bookings‑DAG | Вы сделали полный reset с удалением томов (`docker compose down -v` / `make clean`), поэтому демобаза bookings не установлена. Запустите `make bookings-init` и повторите DAG. |
|
||||
| Ошибка подключения к Greenplum | Убедитесь, что контейнер `greenplum` стал статусом `healthy` (проверьте `docker compose ps`) |
|
||||
| Не открывается порт 8080/5433/5434/5435 | Проверьте, что эти порты не заняты локальными сервисами; при необходимости остановите их или измените порты в `.env`/`docker-compose.yml` |
|
||||
| Нет файла в `./data` после запуска DAG | Проверьте логи задачи `generate_csv`, убедитесь, что `CSV_DIR` смонтирован в docker-compose |
|
||||
| Команда `make` не найдена | Используйте полные команды `docker compose` или установите make |
|
||||
| Greenplum не стартует/падает при старте | Попробуйте `make down && make up`. Если не помогло — полный reset: `make clean && make up` (удалит тома). |
|
||||
| `database "demo" does not exist` в bookings‑DAG | Вы сделали reset с удалением volumes (`make clean` / `docker compose down -v`). Запустите `make bookings-init` и повторите DAG. |
|
||||
| Ошибка подключения к Greenplum | Убедитесь, что контейнер `greenplum` имеет статус `healthy` (`docker compose ps`) |
|
||||
| `protocol "pxf" does not exist` | Перезапустите `greenplum` и повторите `bookings_stg_ddl`/`make ddl-gp` — расширение `pxf` создаётся автоматически при старте контейнера. |
|
||||
| PXF не отвечает (Connection refused к порту 5888) | Проверьте `pxf cluster status` в контейнере `greenplum` и перезапустите сервис `greenplum`. |
|
||||
| PXF не подхватывает изменения конфигов | Пересоберите образ (`make build`) и перезапустите `greenplum`. Для принудительной перезаписи файлов задайте `PXF_SEED_OVERWRITE=1`. |
|
||||
| DAG `bookings_to_gp_stage` падает на внешней таблице/подключении к bookings | Убедитесь, что запущен контейнер `bookings-db` (`docker compose ps`, при необходимости `docker compose start bookings-db`), и выполнены `make bookings-init` и `make ddl-gp` или DAG `bookings_stg_ddl` |
|
||||
| DAG `bookings_to_gp_stage` ругается на отсутствующие таблицы stg | Запустите DAG `bookings_stg_ddl` (или выполните `make ddl-gp`), затем повторите запуск |
|
||||
| DAG не видит Greenplum/DEMObase по Airflow Connections | Убедитесь, что контейнеры `greenplum` и `bookings-db` запущены (`docker compose ps`). Подключения `greenplum_conn` и `bookings_db` задаются через переменные окружения `AIRFLOW_CONN_...` и могут не отображаться в UI, но `PostgresOperator` всё равно найдёт их по `conn_id`. При необходимости вы можете создать/отредактировать их вручную в разделе Connections. |
|
||||
|
||||
---
|
||||
|
||||
## 📁 Структура проекта
|
||||
|
||||
```
|
||||
├── docker-compose.yml # Описание всех сервисов
|
||||
├── Dockerfile.airflow # Образ Airflow с зависимостями
|
||||
├── Dockerfile.greenplum # Образ Greenplum с интегрированным PXF
|
||||
├── .env.example # Шаблон настроек
|
||||
├── Makefile # Удобные команды для работы
|
||||
├── README.md # Обзор стенда
|
||||
├── TESTING.md # Пошаговый план проверки
|
||||
├── educational-tasks.md # Учебные задания для менти
|
||||
├── airflow/
|
||||
│ └── dags/ # Файлы workflow (DAG)
|
||||
│ ├── csv_to_greenplum.py
|
||||
│ ├── csv_to_greenplum_dq.py
|
||||
│ └── bookings_to_gp_stage.py
|
||||
├── bookings/ # Скрипты и файлы для демобазы bookings в Postgres
|
||||
├── sql/
|
||||
│ └── ddl_gp.sql # Общий DDL для Greenplum (подключает stg/src-скрипты)
|
||||
├── docs/ # Дополнительные документы (архитектура, bookings/STG, PXF)
|
||||
├── tests/ # Автоматические тесты (pytest)
|
||||
└── pxf/ # Конфигурация и файлы для PXF
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 Советы для дальнейшего обучения
|
||||
|
||||
1. **Поэкспериментируйте с DAG** — измените параметры генерации данных или размер батча
|
||||
2. **Добавьте свои проверки** — расширьте DAG `csv_to_greenplum_dq.py`
|
||||
3. **Попробуйте другие источники** — замените генератор данных на чтение из файла или API
|
||||
4. **Изучите Airflow deeper** — добавьте зависимости между задачами, настройте расписания
|
||||
|
||||
---
|
||||
|
||||
## ✅ Тестирование
|
||||
|
||||
- Локальные проверки: `make test` (pytest). Для форматирования — `make fmt`, для проверки — `make lint`.
|
||||
- Пошаговый сценарий с Docker (включая негативные кейсы и reset) — см. `TESTING.md`.
|
||||
- Полный smoke-тест стенда (сносит volumes!): `make e2e-smoke` — поднимает стек с нуля, прогоняет `csv_to_greenplum` и `bookings_to_gp_stage` через `airflow dags test` и проверяет, что в `public.orders` и `stg.bookings` появились строки.
|
||||
|
||||
|
||||
---
|
||||
| DAG `bookings_to_gp_stage` ругается на отсутствующие таблицы stg | Запустите `bookings_stg_ddl` (или выполните `make ddl-gp`), затем повторите запуск |
|
||||
| Порты 8080/5434/5435 заняты | Остановите локальные сервисы или измените порты в `.env`/`docker-compose.yml` |
|
||||
|
||||
## Благодарности
|
||||
|
||||
- **Postgres Pro** — за демо-БД bookings и генератор данных `demodb`: https://github.com/postgrespro/demodb (лицензия MIT: https://github.com/postgrespro/demodb/blob/main/LICENSE).
|
||||
- **Postgres Pro** — за демо‑БД bookings и генератор данных `demodb`: https://github.com/postgrespro/demodb (лицензия MIT: https://github.com/postgrespro/demodb/blob/main/LICENSE).
|
||||
- **woblerr** — за Docker-сборку Greenplum: https://github.com/woblerr/docker-greenplum (образ: `woblerr/greenplum`, лицензия MIT: https://github.com/woblerr/docker-greenplum/blob/master/LICENSE).
|
||||
|
||||
Удачи в изучении Data Engineering! 🚀
|
||||
|
||||
+3
-2
@@ -80,8 +80,9 @@
|
||||
- Хостовые CSV: каталог `data/` (можно открыть любой файл и убедиться в структуре).
|
||||
|
||||
## 9. Завершение работы
|
||||
- `make down` — выключает сервисы и удаляет тома (перезапишет данные в Greenplum!).
|
||||
- При необходимости сохранить данные: скопировать CSV из `data/` и дампы из контейнера до `make down`.
|
||||
- `make down` — выключает сервисы и удаляет контейнеры/сети (volumes сохраняются).
|
||||
- Полный сброс данных (удаляет volumes): `make clean`.
|
||||
- При необходимости сохранить данные: скопировать CSV из `data/` и сделать дампы до `make clean`.
|
||||
|
||||
## Текущий статус (пример успешного прогона)
|
||||
- `uv run pytest -q` — 11 passed, 2 smoke-теста DAG пропущены (Airflow не установлен в venv).
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# Документация
|
||||
|
||||
Этот каталог содержит дополнительные материалы к учебному стенду.
|
||||
|
||||
## Быстрый путь (для менти)
|
||||
|
||||
- [Быстрый старт и команды](../README.md)
|
||||
- [Учебные задания](../educational-tasks.md)
|
||||
- [План тестирования и проверки](../TESTING.md)
|
||||
- [Главный учебный DAG: bookings → stg](bookings_to_gp_stage.md)
|
||||
|
||||
## Технические детали (опционально)
|
||||
|
||||
- [Как устроен Docker-стенд (образы, Connections, переменные окружения)](stack.md)
|
||||
- [PXF в этом проекте (проектная реализация)](internal/pxf_bookings.md)
|
||||
- [Дизайн stg для bookings (черновик)](internal/bookings_stg_design.md)
|
||||
- [Про время/UTC в bookings (черновик)](internal/bookings_tz.md)
|
||||
@@ -0,0 +1,100 @@
|
||||
# DAG `bookings_to_gp_stage`: `bookings-db` → `stg` в Greenplum
|
||||
|
||||
Этот DAG — основной учебный пример в стенде. Он показывает путь данных из источника **Postgres**
|
||||
(`bookings-db`, демо‑БД `demo`) в сырой слой **STG** в **Greenplum** с инкрементальной загрузкой
|
||||
и простой проверкой качества данных.
|
||||
|
||||
## Что делает DAG
|
||||
|
||||
- В источнике (`bookings-db`) генерирует следующий учебный день данных в `bookings.bookings`
|
||||
(генератор всегда “шагает” вперёд от `max(book_date)`).
|
||||
- В Greenplum загружает инкремент в `stg.bookings` через внешнюю таблицу `stg.bookings_ext` (PXF).
|
||||
- Сверяет количество строк между источником (за окно инкремента) и загруженным батчем.
|
||||
|
||||
## Что должно быть готово перед запуском
|
||||
|
||||
1) Стек поднят:
|
||||
|
||||
```bash
|
||||
make up
|
||||
```
|
||||
|
||||
2) Демо‑БД bookings установлена и содержит данные:
|
||||
|
||||
```bash
|
||||
make bookings-init
|
||||
```
|
||||
|
||||
3) В Greenplum созданы `stg.bookings_ext` и `stg.bookings` (выберите один вариант):
|
||||
|
||||
- учебный вариант: запустить DAG `bookings_stg_ddl` в Airflow UI;
|
||||
- технический шорткат: `make ddl-gp`.
|
||||
|
||||
4) Airflow Connections:
|
||||
|
||||
- `bookings_db` — подключение к источнику `bookings-db`;
|
||||
- `greenplum_conn` — подключение к Greenplum.
|
||||
|
||||
По умолчанию они задаются через переменные окружения `AIRFLOW_CONN_...` в `docker-compose.yml`,
|
||||
поэтому могут не отображаться в UI — для `PostgresOperator` это нормально.
|
||||
|
||||
## Как запустить
|
||||
|
||||
1) Откройте Airflow UI: http://localhost:8080 (admin/admin).
|
||||
2) Запустите DAG `bookings_to_gp_stage` вручную (Trigger DAG).
|
||||
3) Дождитесь статуса Success у всех задач.
|
||||
|
||||
## Как это работает внутри (по шагам)
|
||||
|
||||
1) `generate_bookings_day`
|
||||
|
||||
- выполняет `sql/src/bookings_generate_day_if_missing.sql` в `bookings-db`;
|
||||
- если `bookings.bookings` пустая — вызывает `generate(...)` на `BOOKINGS_INIT_DAYS`;
|
||||
- иначе — вызывает `continue(...)`, добавляя ровно один следующий день.
|
||||
|
||||
2) `load_bookings_to_stg`
|
||||
|
||||
- выполняет `sql/stg/bookings_load.sql` в Greenplum;
|
||||
- берёт строки из `stg.bookings_ext`, которые попадают в новое окно инкремента;
|
||||
- вставляет их в `stg.bookings`, добавляя тех.колонки:
|
||||
- `src_created_at_ts` (опорная метка времени для инкремента),
|
||||
- `load_dttm`,
|
||||
- `batch_id={{ run_id }}`.
|
||||
|
||||
3) `check_row_counts`
|
||||
|
||||
- выполняет `sql/stg/bookings_dq.sql` в Greenplum;
|
||||
- считает количество строк в источнике за то же окно инкремента и сравнивает с количеством строк,
|
||||
вставленных в `stg.bookings` для текущего `batch_id`;
|
||||
- при расхождении делает `RAISE EXCEPTION` с понятным текстом.
|
||||
|
||||
4) `finish_summary`
|
||||
|
||||
- логирует краткую сводку в конце запуска.
|
||||
|
||||
## Как проверить результат
|
||||
|
||||
```bash
|
||||
make gp-psql
|
||||
```
|
||||
|
||||
Примеры запросов:
|
||||
|
||||
```sql
|
||||
SELECT COUNT(*) FROM stg.bookings;
|
||||
|
||||
SELECT
|
||||
src_created_at_ts,
|
||||
load_dttm,
|
||||
batch_id
|
||||
FROM stg.bookings
|
||||
ORDER BY src_created_at_ts DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
## Типичные ошибки
|
||||
|
||||
- `database "demo" does not exist`: демо‑БД не установлена → выполните `make bookings-init`.
|
||||
- Ошибки про `stg.bookings_ext`/`stg.bookings`: не применён DDL → запустите `bookings_stg_ddl` или `make ddl-gp`.
|
||||
- Ошибки PXF (`protocol "pxf" does not exist`, connection refused): перезапустите `greenplum` и повторите DDL.
|
||||
Для технических деталей см. `docs/internal/pxf_bookings.md`.
|
||||
@@ -68,7 +68,7 @@ DDL будет добавлен в `sql/ddl_gp.sql` в блоке DDL для Gre
|
||||
- считаем режим `full` — загружаем все строки из `stg.bookings_ext`.
|
||||
- При последующих запусках:
|
||||
- читаем `max(src_created_at_ts)` из `stg.bookings` за все предыдущие загрузки;
|
||||
- считаем, что нужно загрузить только строки, где `src_created_at_ts` больше этой максимальной метки и не позже конца текущего учебного дня.
|
||||
- загружаем строки, где `src_created_at_ts` больше этой максимальной метки (верхняя граница по времени не задаётся).
|
||||
|
||||
Таким образом, вся логика инкремента «замкнута» на один техно‑столбец `src_created_at_ts`, который студент потом сможет использовать и на следующих слоях (например, в CDC‑логике).
|
||||
|
||||
@@ -88,7 +88,7 @@ DDL будет добавлен в `sql/ddl_gp.sql` в блоке DDL для Gre
|
||||
|
||||
- `dag_id`: `bookings_to_gp_stage`.
|
||||
- Основные параметры:
|
||||
- `batch_id` (по умолчанию `{{ ds_nodash }}`) — метка батча, которая попадает в `stg.bookings.batch_id`;
|
||||
- `batch_id` (в текущей реализации `{{ run_id }}`) — метка батча, которая попадает в `stg.bookings.batch_id`;
|
||||
- подключения:
|
||||
- `bookings_db_conn_id` — Airflow connection к `bookings-db` (в коде DAG — `BOOKINGS_CONN_ID = "bookings_db"`);
|
||||
- `greenplum_conn_id` — Airflow connection к Greenplum (`GREENPLUM_CONN_ID = "greenplum_conn"`).
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
# Мини‑README по учебному DAG bookings_to_gp_stage (черновик)
|
||||
|
||||
_Внутренний файл, чтобы не забыть договорённости. Перед итоговой сдачей документацию по блоку bookings/STG нужно будет аккуратно собрать и переписать._
|
||||
|
||||
## 1. Что делает DAG
|
||||
|
||||
- DAG `bookings_to_gp_stage` показывает учебный поток:
|
||||
- источник: демо‑БД `bookings-db` (Postgres, схема `bookings`, таблица `bookings.bookings`);
|
||||
- при каждом запуске генерируется один учебный день данных (идемпотентно);
|
||||
- данные из `bookings.bookings` переливаются в сырой слой `stg.bookings` в Greenplum через PXF‑внешнюю таблицу `stg.bookings_ext`.
|
||||
- Слой `stg` задуман как «сырой»:
|
||||
- все бизнес‑колонки (`book_ref`, `book_date`, `total_amount`) хранятся как `TEXT`;
|
||||
- есть тех.колонки `src_created_at_ts`, `load_dttm`, `batch_id`.
|
||||
|
||||
Подробный дизайн описан в `docs/internal/bookings_stg_design.md`.
|
||||
|
||||
## 2. Что нужно, чтобы DAG завёлся
|
||||
|
||||
Минимальные предпосылки:
|
||||
|
||||
- Стенд поднят: `make up`.
|
||||
- Демо‑БД bookings инициализирована: `make bookings-init`.
|
||||
- В Greenplum применён DDL (созданы схема `stg` и таблицы `stg.bookings_ext` / `stg.bookings`):
|
||||
- учебный вариант: запустить DAG `bookings_stg_ddl` (он использует `sql/stg/bookings_ddl.sql`);
|
||||
- технический шорткат: `make ddl-gp` применяет все DDL разом вручную. Команда сама не вызывается при старте контейнеров, её нужно запустить явно.
|
||||
- В Airflow есть коннекты:
|
||||
- `greenplum_conn` — к Greenplum;
|
||||
- `bookings_db` — к сервису `bookings-db`.
|
||||
По умолчанию они задаются через переменные окружения `AIRFLOW_CONN_...` в docker-compose,
|
||||
поэтому могут не отображаться в UI, но `PostgresOperator` найдёт их по `conn_id`. При желании
|
||||
их можно создать/отредактировать вручную через Admin → Connections.
|
||||
|
||||
## 3. Последовательность задач в DAG
|
||||
|
||||
- `generate_bookings_day`:
|
||||
- PostgresOperator к `bookings-db`;
|
||||
- выполняет SQL `/sql/src/bookings_generate_day_if_missing.sql`;
|
||||
- скрипт смотрит на `max(book_date)` в `bookings.bookings`:
|
||||
- если база пустая — берёт стартовую дату из GUC и генерирует `bookings.init_days` суток;
|
||||
- если данные уже есть — добавляет один следующий учебный день после `max(book_date)` и пишет NOTICE с интервалом генерации.
|
||||
- `load_bookings_to_stg`:
|
||||
- PostgresOperator к Greenplum;
|
||||
- выполняет SQL `/sql/stg/bookings_load.sql`;
|
||||
- считает «старый» максимум `src_created_at_ts` (по предыдущим батчам) и грузит только новые строки из `stg.bookings_ext`, заполняя `src_created_at_ts`, `load_dttm`, `batch_id={{ ds_nodash }}`.
|
||||
- `check_row_counts`:
|
||||
- PostgresOperator к Greenplum;
|
||||
- выполняет SQL `/sql/stg/bookings_dq.sql`;
|
||||
- за то же окно инкремента считает количество строк в источнике и в `stg.bookings` (по текущему `batch_id`);
|
||||
- при расхождении делает `RAISE EXCEPTION` с понятным текстом ошибки.
|
||||
- `finish_summary`:
|
||||
- логирует итог выполнения DAG за одно срабатывание.
|
||||
|
||||
## 4. Как этим пользоваться студенту (черновой сценарий)
|
||||
|
||||
1. Поднять стенд и подготовить источники:
|
||||
- `make up` (Airflow инициализируется автоматически при первом старте)
|
||||
- `make bookings-init`
|
||||
- `make ddl-gp`
|
||||
2. Открыть Airflow UI (`http://localhost:8080`) и включить DAG `bookings_to_gp_stage`.
|
||||
3. Вызвать `Trigger` DAG (дату логического запуска можно оставить по умолчанию — она используется только как метка `batch_id`).
|
||||
4. Посмотреть:
|
||||
- в `bookings-db` ― что появился день с бронированиями;
|
||||
- в Greenplum (`make gp-psql`) — данные в `stg.bookings`:
|
||||
- `SELECT * FROM stg.bookings LIMIT 10;`
|
||||
- `SELECT src_created_at_ts, load_dttm, batch_id FROM stg.bookings ORDER BY src_created_at_ts DESC LIMIT 10;`
|
||||
5. Перезапустить DAG ещё несколько раз и увидеть, что:
|
||||
- генерация в `bookings.bookings` идёт по одному дню вперёд от текущего `max(book_date)`;
|
||||
- в `stg.bookings` появляются только новые записи (delta), помеченные разными `batch_id`.
|
||||
|
||||
## 5. Примечания «на потом»
|
||||
|
||||
- Текущая документация по блоку bookings/STG разбросана:
|
||||
- `README.md` (общий обзор стенда),
|
||||
- `docs/internal/bookings_tz.md` (источник bookings),
|
||||
- `docs/internal/pxf_bookings.md` (PXF),
|
||||
- `docs/internal/bookings_stg_design.md` (дизайн STG),
|
||||
- этот файл (мини‑README по DAG).
|
||||
- В будущем всё это нужно будет собрать в одну понятную историю для студента:
|
||||
- отдельный раздел «Учебный пример: bookings → stg → dwh»;
|
||||
- скриншоты DAG, примеры запросов и типичные ошибки.
|
||||
@@ -143,7 +143,7 @@
|
||||
- `docker-compose.yml` (сервис `greenplum`: `build`, `hostname`, env, healthcheck)
|
||||
- `pxf/init/10_pxf_bookings.sh` (ensure‑логика)
|
||||
- `pxf/init/start_greenplum_with_pxf.sh` (старт контейнера)
|
||||
- `README.md` (раздел «Greenplum + PXF: свой образ»)
|
||||
- `docs/stack.md` (раздел «Greenplum + PXF: свой образ»)
|
||||
|
||||
## 10. Известная проблема: после `docker compose stop/start` Greenplum может упасть (auth для PXF)
|
||||
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
# Технические детали стенда (Docker / Airflow / Greenplum)
|
||||
|
||||
Этот документ не обязателен для прохождения лабораторных, но полезен, если вы:
|
||||
|
||||
- хотите понять, как устроен стенд “под капотом”;
|
||||
- меняете конфиги/зависимости и пересобираете образы;
|
||||
- отлаживаете проблемы со стартом Greenplum/PXF или Connections в Airflow.
|
||||
|
||||
## Make (опционально, но удобно)
|
||||
|
||||
Если `make` не установлен, можно пользоваться `docker compose ...`.
|
||||
Но с `make` команды короче и проще.
|
||||
|
||||
Установка `make` (если нужно):
|
||||
|
||||
- Linux (Debian/Ubuntu): `sudo apt install -y make`
|
||||
- macOS: `brew install make`
|
||||
- Windows:
|
||||
- WSL: `sudo apt install -y make`
|
||||
- Chocolatey: `choco install make`
|
||||
- Scoop: `scoop install make`
|
||||
|
||||
Примеры:
|
||||
|
||||
```bash
|
||||
make up
|
||||
make logs
|
||||
make gp-psql
|
||||
```
|
||||
|
||||
## Airflow Connections
|
||||
|
||||
Готовые DAG по умолчанию подключаются к БД через Airflow Connections:
|
||||
|
||||
- `greenplum_conn` — Greenplum;
|
||||
- `bookings_db` — демо‑БД bookings (`bookings-db`).
|
||||
|
||||
В `docker-compose.yml` Connections задаются через переменные окружения `AIRFLOW_CONN_...`,
|
||||
поэтому они могут не отображаться в UI — для DAG это нормально.
|
||||
|
||||
Если нужно завести вручную:
|
||||
|
||||
1) Airflow UI → Admin → Connections → Add a new record
|
||||
2) Пример для Greenplum:
|
||||
- Conn Id: `greenplum_conn`
|
||||
- Conn Type: `Postgres`
|
||||
- Host: `greenplum`
|
||||
- Schema: `gp_dwh`
|
||||
- Login/Password: `gpadmin` / `gpadmin`
|
||||
- Port: `5432`
|
||||
|
||||
## Greenplum + PXF: свой образ
|
||||
|
||||
Greenplum собирается из собственного `Dockerfile.greenplum`, чтобы:
|
||||
|
||||
- не ловить проблемы с правами/`chown` при bind‑mount конфигов;
|
||||
- держать PXF‑конфиги и JDBC‑драйвер внутри образа;
|
||||
- делать старт контейнера идемпотентным.
|
||||
|
||||
При старте контейнера:
|
||||
|
||||
- seed‑конфиги PXF докладываются в `PXF_BASE` на persistent volume;
|
||||
- создаются каталоги `PXF_BASE/run` и `PXF_BASE/logs`;
|
||||
- расширение `pxf` создаётся автоматически, когда Greenplum становится доступен (с ретраями).
|
||||
|
||||
Полезные команды:
|
||||
|
||||
```bash
|
||||
make build # пересобрать образы
|
||||
docker compose ps # проверить health
|
||||
```
|
||||
|
||||
Перезапись seed‑файлов в `PXF_BASE`:
|
||||
|
||||
- `PXF_SEED_OVERWRITE=1` — перезаписать конфиги при старте;
|
||||
- `PXF_SYNC_ON_START=1` — выполнить `pxf cluster sync` при старте.
|
||||
|
||||
Подробнее: `docs/internal/pxf_bookings.md`.
|
||||
|
||||
## Airflow: свой образ
|
||||
|
||||
Airflow тоже собирается из собственного `Dockerfile.airflow`, чтобы зависимости ставились при сборке,
|
||||
а не во время старта контейнеров.
|
||||
|
||||
Если меняли `airflow/requirements.txt` или `Dockerfile.airflow`, пересоберите образы:
|
||||
|
||||
```bash
|
||||
make build
|
||||
make up
|
||||
```
|
||||
|
||||
## Локальное окружение разработчика (uv)
|
||||
|
||||
Локальным окружением управляет `uv` — он создаёт `.venv` из `pyproject.toml` / `uv.lock`.
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
make test
|
||||
make lint
|
||||
make fmt
|
||||
```
|
||||
|
||||
Не устанавливайте зависимости через `pip install --user ...` — это часто ломает окружение и IDE.
|
||||
|
||||
## Переменные окружения (`.env`)
|
||||
|
||||
Все настройки лежат в `.env` (шаблон: `.env.example`).
|
||||
|
||||
### Greenplum
|
||||
|
||||
- `GP_USER`, `GP_PASSWORD`, `GP_DB`
|
||||
- `GP_PORT` — внутренний порт в Docker-сети (обычно `5432`), внешний порт на хосте фиксирован на `5435`
|
||||
|
||||
### bookings-db (Postgres)
|
||||
|
||||
- `BOOKINGS_DB_USER`, `BOOKINGS_DB_PASSWORD`
|
||||
- `BOOKINGS_DB_PORT` — внешний порт (по умолчанию `5434`)
|
||||
- `BOOKINGS_START_DATE` — стартовая дата модельного времени
|
||||
- `BOOKINGS_INIT_DAYS` — сколько дней генерировать при первом `make bookings-init`
|
||||
- `BOOKINGS_JOBS` — число джобов генератора (по умолчанию `1`)
|
||||
|
||||
### CSV pipeline (побочный пример)
|
||||
|
||||
- `CSV_DIR` — путь к каталогу с CSV внутри контейнеров Airflow (по умолчанию `/opt/airflow/data`)
|
||||
- `CSV_ROWS` — количество строк, генерируемых DAG (по умолчанию `1000`)
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
### 2.2. Знакомство с STG в Greenplum
|
||||
|
||||
1. Прочитайте `sql/stg/bookings_ddl.sql` и мини‑README `docs/internal/bookings_stg_readme.md` (если интересно — `docs/internal/bookings_stg_design.md`).
|
||||
1. Прочитайте `sql/stg/bookings_ddl.sql` и краткое описание потока `docs/bookings_to_gp_stage.md` (если интересно — `docs/internal/bookings_stg_design.md`).
|
||||
2. Ответьте себе на вопросы:
|
||||
- чем внешняя таблица `stg.bookings_ext` отличается от внутренней `stg.bookings`;
|
||||
- зачем нужны тех.колонки `src_created_at_ts`, `load_dttm`, `batch_id`;
|
||||
@@ -111,12 +111,12 @@
|
||||
- `sql/src/bookings_generate_day_if_missing.sql`
|
||||
- `sql/stg/bookings_load.sql`
|
||||
- `sql/stg/bookings_dq.sql`
|
||||
3. Соотнесите шаги DAG с документом `docs/internal/bookings_stg_readme.md`:
|
||||
3. Соотнесите шаги DAG с документом `docs/bookings_to_gp_stage.md`:
|
||||
- генерация учебного дня в `bookings.bookings`;
|
||||
- загрузка инкремента в `stg.bookings`;
|
||||
- проверка количества строк между источником и STG.
|
||||
4. Обратите внимание, как в DAG используется логическая дата запуска:
|
||||
- `{{ ds_nodash }}` используется как `batch_id` — метка загрузки в таблице `stg.bookings` для конкретного запуска;
|
||||
- `{{ run_id }}` используется как `batch_id` — метка загрузки в таблице `stg.bookings` для конкретного запуска;
|
||||
- сами даты данных (какие дни есть в `bookings.bookings`) определяются генератором по `max(book_date)`, а не по `ds`.
|
||||
|
||||
На этом этапе достаточно понять общую цепочку. Детальные задания по переработке модели данных и построению ODS/DDS/DM слоёв будут добавлены позже.
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
-- Чтобы не ломать задания, новые объекты лучше добавлять в отдельные файлы
|
||||
-- и подключать их отсюда, а существующие определения не удалять.
|
||||
--
|
||||
-- Подробнее про STG/bookings: см. docs/internal/bookings_stg_readme.md.
|
||||
-- Подробнее про STG/bookings: см. docs/bookings_to_gp_stage.md.
|
||||
|
||||
-- Таблица для CSV‑пайплайна (csv_to_greenplum).
|
||||
\i base/orders_ddl.sql
|
||||
|
||||
Reference in New Issue
Block a user