Доводка стилистики документации

This commit is contained in:
2026-02-28 22:12:22 +03:00
parent 159ee99a32
commit 3dcaeb85ce
19 changed files with 60 additions and 44 deletions
+3 -2
View File
@@ -91,8 +91,9 @@ SELECT * FROM stg.bookings ORDER BY src_created_at_ts DESC LIMIT 10;
Основные (для потока bookings → DWH): Основные (для потока bookings → DWH):
- `bookings_stg_ddl` — создаёт `stg.bookings_ext`/`stg.bookings` и `stg.tickets_ext`/`stg.tickets` в Greenplum; - `bookings_stg_ddl` — создаёт `stg.bookings_ext`/`stg.bookings` и `stg.tickets_ext`/`stg.tickets` в Greenplum;
- `bookings_to_gp_stage` — генерирует учебный день в `bookings-db`, грузит инкремент в `stg.bookings` и `stg.tickets` - `bookings_stg_ddl` — создаёт/обновляет весь STG слой для bookings (9 таблиц: bookings, tickets, airports, airplanes,
(через PXF), затем выполняет DQ‑проверки. routes, seats, flights, segments, boarding_passes; включая внешние `*_ext` через PXF);
- `bookings_to_gp_stage` — генерирует учебный день в `bookings-db`, затем загружает данные в STG и выполняет DQ‑проверки.
Вспомогательные (побочный трек с CSV): Вспомогательные (побочный трек с CSV):
+2 -2
View File
@@ -38,10 +38,10 @@
- Проверить, что все 5 задач Success и логи содержат `Проверка пройдена`. - Проверить, что все 5 задач Success и логи содержат `Проверка пройдена`.
- DAG `bookings_to_gp_stage` (полная проверка цепочки bookings → Greenplum STG): - DAG `bookings_to_gp_stage` (полная проверка цепочки bookings → Greenplum STG):
- предварительно выполнить один раз: `make bookings-init` (установка демобазы `demo` в контейнере `bookings-db`) и `make ddl-gp` (создаёт `stg.bookings_ext` и `stg.bookings` в Greenplum); - предварительно выполнить один раз: `make bookings-init` (установка демобазы `demo` в контейнере `bookings-db`) и `make ddl-gp` (создаёт STG слой в Greenplum, включая внешние `*_ext` через PXF);
- важно: DAG `bookings_stg_ddl` **не** создаёт базу `demo` в `bookings-db`; если вы делали `docker compose down -v` / `make clean`, `make bookings-init` обязателен; - важно: DAG `bookings_stg_ddl` **не** создаёт базу `demo` в `bookings-db`; если вы делали `docker compose down -v` / `make clean`, `make bookings-init` обязателен;
- включить DAG `bookings_to_gp_stage` и запустить `Trigger DAG`; - включить DAG `bookings_to_gp_stage` и запустить `Trigger DAG`;
- убедиться, что все задачи (`generate_bookings_day`, `load_bookings_to_stg`, `check_row_counts`, `finish_summary`) завершились со статусом Success; - убедиться, что все задачи завершились со статусом Success (включая загрузки справочников/транзакций и DQ);
- при желании проверить данные: в `bookings-db` появился новый день, а в Greenplum в `stg.bookings` — строки с актуальным `batch_id` (см. пример запросов в разделе 5). - при желании проверить данные: в `bookings-db` появился новый день, а в Greenplum в `stg.bookings` — строки с актуальным `batch_id` (см. пример запросов в разделе 5).
- (опционально, для менторов/разработчиков) Smoke-тест DAG через Airflow CLI без UI: - (опционально, для менторов/разработчиков) Smoke-тест DAG через Airflow CLI без UI:
+9 -5
View File
@@ -1,8 +1,11 @@
from __future__ import annotations from __future__ import annotations
""" """
Учебный DAG: создаёт схему stg и таблицы bookings_ext/bookings/tickets в Greenplum. Учебный DAG: создаёт/обновляет слой stg в Greenplum для демо-источника bookings.
Запускается вручную перед DAG загрузки bookings_to_gp_stage или после изменения DDL.
Запускается вручную перед DAG загрузки `bookings_to_gp_stage` или после изменения DDL.
Создаёт внешние таблицы PXF (`*_ext`) и внутренние таблицы STG (9 таблиц: bookings, tickets,
airports, airplanes, routes, seats, flights, segments, boarding_passes).
""" """
from datetime import timedelta from datetime import timedelta
@@ -23,8 +26,8 @@ with DAG(
catchup=False, catchup=False,
template_searchpath="/sql", template_searchpath="/sql",
default_args=default_args, default_args=default_args,
tags=["demo", "greenplum", "ddl", "bookings", "tickets", "stg"], tags=["demo", "greenplum", "ddl", "bookings", "stg"],
description="Создаёт/обновляет stg.bookings_ext/bookings/tickets для учебного DAG", description="Учебный DDL DAG: создаёт/обновляет stg.* (PXF external + internal STG) для bookings",
) as dag: ) as dag:
apply_stg_bookings_ddl = PostgresOperator( apply_stg_bookings_ddl = PostgresOperator(
task_id="apply_stg_bookings_ddl", task_id="apply_stg_bookings_ddl",
@@ -82,7 +85,8 @@ with DAG(
sql="stg/boarding_passes_ddl.sql", sql="stg/boarding_passes_ddl.sql",
) )
# Сначала создаются справочники, затем транзакционные таблицы (последовательно) # DDL применяем последовательно, чтобы порядок был понятным для новичков,
# а ошибки — воспроизводимыми (в логах сразу видно, на каком объекте упали).
( (
apply_stg_bookings_ddl apply_stg_bookings_ddl
>> apply_stg_tickets_ddl >> apply_stg_tickets_ddl
+8 -4
View File
@@ -13,6 +13,8 @@ from __future__ import annotations
- генератор в демо-БД bookings добавляет следующий учебный день после max(book_date); - генератор в демо-БД bookings добавляет следующий учебный день после max(book_date);
- загрузка в Greenplum берёт все строки, появившиеся после предыдущих батчей; - загрузка в Greenplum берёт все строки, появившиеся после предыдущих батчей;
- `run_id` используется как метка запуска (в `batch_id`, в логах и DQ). - `run_id` используется как метка запуска (в `batch_id`, в логах и DQ).
Важно: для инкрементальных таблиц «пустое окно инкремента» допустимо (это не ошибка).
""" """
from datetime import timedelta from datetime import timedelta
@@ -56,7 +58,7 @@ with DAG(
template_searchpath="/sql", template_searchpath="/sql",
default_args=default_args, default_args=default_args,
tags=["demo", "bookings", "greenplum", "stg"], tags=["demo", "bookings", "greenplum", "stg"],
description="Учебный DAG: загрузка из bookings-db в stg.bookings и stg.tickets (Greenplum)", description="Учебный DAG: загрузка из bookings-db в слой stg (Greenplum) + DQ проверки",
) as dag: ) as dag:
# 1. Генерируем один (или несколько стартовых) учебный день в демо-БД bookings # 1. Генерируем один (или несколько стартовых) учебный день в демо-БД bookings
generate_bookings_day = PostgresOperator( generate_bookings_day = PostgresOperator(
@@ -180,7 +182,7 @@ with DAG(
sql="stg/boarding_passes_dq.sql", sql="stg/boarding_passes_dq.sql",
) )
# 6. Финальный лог/сводка # Финальный лог/сводка
finish_summary = PythonOperator( finish_summary = PythonOperator(
task_id="finish_summary", task_id="finish_summary",
python_callable=_finish_summary, python_callable=_finish_summary,
@@ -190,13 +192,15 @@ with DAG(
generate_bookings_day >> load_bookings_to_stg >> check_row_counts generate_bookings_day >> load_bookings_to_stg >> check_row_counts
check_row_counts >> load_tickets_to_stg >> check_tickets_dq check_row_counts >> load_tickets_to_stg >> check_tickets_dq
# Затем загружаются справочники (последовательная загрузка) # Затем загружаются справочники.
# Для простоты (и более понятных логов для новичков) делаем это последовательно.
# Если позже понадобится ускорить DAG, эти шаги можно распараллелить, сохранив зависимости.
check_tickets_dq >> load_airports_to_stg >> check_airports_dq check_tickets_dq >> load_airports_to_stg >> check_airports_dq
check_airports_dq >> load_airplanes_to_stg >> check_airplanes_dq check_airports_dq >> load_airplanes_to_stg >> check_airplanes_dq
check_airplanes_dq >> load_routes_to_stg >> check_routes_dq check_airplanes_dq >> load_routes_to_stg >> check_routes_dq
check_routes_dq >> load_seats_to_stg >> check_seats_dq check_routes_dq >> load_seats_to_stg >> check_seats_dq
# Затем загружаются транзакции (последовательная загрузка) # Затем загружаются транзакции (тоже последовательно, по тем же причинам).
check_seats_dq >> load_flights_to_stg >> check_flights_dq check_seats_dq >> load_flights_to_stg >> check_flights_dq
check_flights_dq >> load_segments_to_stg >> check_segments_dq check_flights_dq >> load_segments_to_stg >> check_segments_dq
check_segments_dq >> load_boarding_passes_to_stg >> check_boarding_passes_dq check_segments_dq >> load_boarding_passes_to_stg >> check_boarding_passes_dq
+4 -2
View File
@@ -29,7 +29,9 @@ make up
make bookings-init make bookings-init
``` ```
3) В Greenplum созданы STG‑объекты `stg.bookings_ext`/`stg.bookings` и `stg.tickets_ext`/`stg.tickets` (выберите один вариант): 3) В Greenplum созданы STG‑объекты (внешние `*_ext` через PXF и внутренние таблицы слоя `stg`)
для всех таблиц потока: `bookings`, `tickets`, `airports`, `airplanes`, `routes`, `seats`, `flights`,
`segments`, `boarding_passes` (выберите один вариант):
- учебный вариант: запустить DAG `bookings_stg_ddl` в Airflow UI; - учебный вариант: запустить DAG `bookings_stg_ddl` в Airflow UI;
- технический шорткат: `make ddl-gp`. - технический шорткат: `make ddl-gp`.
@@ -130,7 +132,7 @@ LIMIT 10;
## Типичные ошибки ## Типичные ошибки
- `database "demo" does not exist`: демо‑БД не установлена → выполните `make bookings-init`. - `database "demo" does not exist`: демо‑БД не установлена → выполните `make bookings-init`.
- Ошибки про `stg.bookings_ext`/`stg.bookings`: не применён DDL → запустите `bookings_stg_ddl` или `make ddl-gp`. - Ошибки про `stg.*`/`stg.*_ext`: не применён DDL → запустите `bookings_stg_ddl` или `make ddl-gp`.
- Ошибки PXF (`protocol "pxf" does not exist`, connection refused): перезапустите `greenplum` и повторите DDL. - Ошибки PXF (`protocol "pxf" does not exist`, connection refused): перезапустите `greenplum` и повторите DDL.
Для технических деталей см. `docs/internal/pxf_bookings.md`. Для технических деталей см. `docs/internal/pxf_bookings.md`.
+3
View File
@@ -1,5 +1,8 @@
# План ETL для загрузки `bookings.tickets` в STG слой # План ETL для загрузки `bookings.tickets` в STG слой
> Архивный документ: это рабочий план, который использовался при разработке.
> Актуальная реализация потока — DAG `bookings_to_gp_stage` и SQL в `sql/stg/`.
**Ветка:** `chore/bookings-etl` **Ветка:** `chore/bookings-etl`
**Цель:** Добавить загрузку таблицы `tickets` в STG слой Greenplum по аналогии с `bookings` **Цель:** Добавить загрузку таблицы `tickets` в STG слой Greenplum по аналогии с `bookings`
+15 -8
View File
@@ -8,6 +8,10 @@ _Внутренний документ для учебного стенда. П
- Цель: показываем путь данных от операционной БД до сырого слоя DWH в Greenplum. - Цель: показываем путь данных от операционной БД до сырого слоя DWH в Greenplum.
- В этом документе описываем только часть `src (bookings-db) → STG (Greenplum)`. Слои ODS/DDS/DM студент проектирует сам по статье про моделирование DWH. - В этом документе описываем только часть `src (bookings-db) → STG (Greenplum)`. Слои ODS/DDS/DM студент проектирует сам по статье про моделирование DWH.
Примечание: в текущей версии стенда слой `stg` содержит не только `bookings`, но и остальные таблицы потока
(`tickets`, `airports`, `airplanes`, `routes`, `seats`, `flights`, `segments`, `boarding_passes`).
Ниже логика разобрана на примере `bookings`, потому что на нём проще показать принципы инкремента и батчей.
Логика на уровне слоёв (по статье): Логика на уровне слоёв (по статье):
- `src`: оперативная система (`bookings-db`, схема `bookings`). - `src`: оперативная система (`bookings-db`, схема `bookings`).
@@ -20,8 +24,8 @@ _Внутренний документ для учебного стенда. П
- Используем одну схему `stg` в Greenplum. - Используем одну схему `stg` в Greenplum.
- В этой схеме будут: - В этой схеме будут:
- внешняя таблица PXF для чтения из `bookings-db`; - внешние таблицы PXF `*_ext` для чтения из `bookings-db`;
- внутренняя таблица STG для долговременного хранения «сырых» данных. - внутренние таблицы STG `stg.*` для долговременного хранения «сырых» данных.
### 2.2. Внешняя таблица (PXF) ### 2.2. Внешняя таблица (PXF)
@@ -31,6 +35,8 @@ _Внутренний документ для учебного стенда. П
- можем использовать «родные» типы из `bookings.bookings` (включая даты/числа); - можем использовать «родные» типы из `bookings.bookings` (включая даты/числа);
- задача внешней таблицы — корректно читать данные из источника, не заниматься приведением типов. - задача внешней таблицы — корректно читать данные из источника, не заниматься приведением типов.
В текущей реализации аналогично созданы внешние таблицы `*_ext` и для остальных сущностей (см. `sql/stg/*_ddl.sql`).
DDL будет добавлен в `sql/ddl_gp.sql` в блоке DDL для Greenplum (примерно по шаблону из `docs/internal/pxf_bookings.md`), с `LOCATION ('pxf://bookings.bookings?PROFILE=JDBC&SERVER=bookings-db')`. DDL будет добавлен в `sql/ddl_gp.sql` в блоке DDL для Greenplum (примерно по шаблону из `docs/internal/pxf_bookings.md`), с `LOCATION ('pxf://bookings.bookings?PROFILE=JDBC&SERVER=bookings-db')`.
### 2.3. Внутренняя таблица STG ### 2.3. Внутренняя таблица STG
@@ -46,7 +52,7 @@ DDL будет добавлен в `sql/ddl_gp.sql` в блоке DDL для Gre
- `src_created_at_ts TIMESTAMP` — дата/время из источника, приведённая к TIMESTAMP: - `src_created_at_ts TIMESTAMP` — дата/время из источника, приведённая к TIMESTAMP:
- используется как опорная колонка для инкрементальной загрузки; - используется как опорная колонка для инкрементальной загрузки;
- заполняется из исходной даты/времени (`created_at` или аналог). - заполняется из опорной даты/времени, принятой для конкретной сущности (например, для `bookings` — из `book_date`).
- `load_dttm TIMESTAMP NOT NULL DEFAULT now()` — когда запись была загружена в STG. - `load_dttm TIMESTAMP NOT NULL DEFAULT now()` — когда запись была загружена в STG.
- `batch_id TEXT NOT NULL` — идентификатор «пачки» (например, `{{ ds_nodash }}` или `run_id` Airflow). - `batch_id TEXT NOT NULL` — идентификатор «пачки» (например, `{{ ds_nodash }}` или `run_id` Airflow).
- при необходимости позже можно добавить `src_system TEXT`, если появятся другие источники. - при необходимости позже можно добавить `src_system TEXT`, если появятся другие источники.
@@ -59,8 +65,8 @@ DDL будет добавлен в `sql/ddl_gp.sql` в блоке DDL для Gre
- Опорная колонка: `src_created_at_ts` (внутреннее имя в STG). - Опорная колонка: `src_created_at_ts` (внутреннее имя в STG).
- Источник значения: - Источник значения:
- берём из соответствующей колонки в `bookings.bookings` (например, `book_date`/`created_at` — будет уточнено при реализации); - для `bookings` используем `book_date` из `bookings.bookings` (в демо‑БД это поле естественно “шагает” по дням);
- при чтении через `stg.bookings_ext` приводим к `TIMESTAMP`. - при чтении через `stg.bookings_ext` приводим к `TIMESTAMP` и сохраняем в `stg.bookings.src_created_at_ts`.
### 3.2. Правила определения full/delta ### 3.2. Правила определения full/delta
@@ -79,8 +85,8 @@ DDL будет добавлен в `sql/ddl_gp.sql` в блоке DDL для Gre
- `dag_id`: `bookings_stg_ddl` (реализован в `airflow/dags/bookings_stg_ddl.py`). - `dag_id`: `bookings_stg_ddl` (реализован в `airflow/dags/bookings_stg_ddl.py`).
- Назначение: один раз (или при изменении схемы) создать необходимые объекты в Greenplum: - Назначение: один раз (или при изменении схемы) создать необходимые объекты в Greenplum:
- схему `stg` (если её ещё нет); - схему `stg` (если её ещё нет);
- внешнюю таблицу `stg.bookings_ext` (PXF → `bookings-db`); - внешние таблицы `*_ext` и внутренние таблицы слоя `stg` для всех сущностей потока
- внутреннюю таблицу `stg.bookings` с текстовыми колонками и тех.полями. (см. `sql/stg/*_ddl.sql`).
- Этот DAG не загружает данные, только подготавливает структуру. - Этот DAG не загружает данные, только подготавливает структуру.
- Вся DDL‑логика (CREATE/ALTER/DROP) сосредоточена здесь; рабочие DAG’и занимаются только DML (INSERT/SELECT). - Вся DDL‑логика (CREATE/ALTER/DROP) сосредоточена здесь; рабочие DAG’и занимаются только DML (INSERT/SELECT).
@@ -115,7 +121,8 @@ DDL будет добавлен в `sql/ddl_gp.sql` в блоке DDL для Gre
- количество строк в `stg.bookings_ext` с `book_date` позже «старого» максимума, - количество строк в `stg.bookings_ext` с `book_date` позже «старого» максимума,
- количество строк в `stg.bookings` для текущего `batch_id`; - количество строк в `stg.bookings` для текущего `batch_id`;
- при расхождении выполняет `RAISE EXCEPTION` с понятным текстом ошибки. - при расхождении выполняет `RAISE EXCEPTION` с понятным текстом ошибки.
4. `finish_summary` 4. Далее — загрузка и DQ для остальных таблиц потока (tickets, справочники, транзакции).
5. `finish_summary`
- PythonOperator, который логирует итог выполнения DAG и напоминает, где смотреть детальные логи. - PythonOperator, который логирует итог выполнения DAG и напоминает, где смотреть детальные логи.
Таким образом, вся бизнес‑логика инкремента и проверок живёт в SQL‑скриптах, а DAG отвечает за оркестрацию и подключение к нужным БД. Для менти это хороший пример разделения ответственности между SQL и Python. Таким образом, вся бизнес‑логика инкремента и проверок живёт в SQL‑скриптах, а DAG отвечает за оркестрацию и подключение к нужным БД. Для менти это хороший пример разделения ответственности между SQL и Python.
+1 -1
View File
@@ -1,6 +1,6 @@
# Временное ТЗ по блоку bookings (для текущей разработки) # Временное ТЗ по блоку bookings (для текущей разработки)
_Этот файл внутренний, удалить перед итоговой сдачей._ _Внутренний файл для наставника: поясняет, как устроен источник `bookings-db` и генерация данных. Студентам обычно не нужен._
- Контейнер `bookings-db` — отдельный сервис Postgres из `docker-compose.yml`, база по умолчанию `demo` (из upstream demodb), без переименований. - Контейнер `bookings-db` — отдельный сервис Postgres из `docker-compose.yml`, база по умолчанию `demo` (из upstream demodb), без переименований.
- Доступ снаружи не блокируем (порт `5434` по умолчанию), чтобы позже читать через PXF и подключаться из Greenplum. - Доступ снаружи не блокируем (порт `5434` по умолчанию), чтобы позже читать через PXF и подключаться из Greenplum.
+3 -3
View File
@@ -32,7 +32,7 @@ WITH (appendonly=true, orientation=row, compresstype=zlib, compresslevel=1)
-- Обоснование: airplane_code — это уникальный идентификатор самолёта. -- Обоснование: airplane_code — это уникальный идентификатор самолёта.
-- Использование airplane_code обеспечивает: -- Использование airplane_code обеспечивает:
-- 1. Равномерное распределение данных по сегментам (airplane_code имеет высокую кардинальность) -- 1. Равномерное распределение данных по сегментам (airplane_code имеет высокую кардинальность)
-- 2. Co-location данных airplanes и routes при JOIN по airplane_code -- 2. Коллокацию данных airplanes и seats при JOIN по airplane_code
-- 3. Co-location данных airplanes и seats при JOIN по airplane_code -- 3. Оптимизацию запросов, которые фильтруют или группируют по airplane_code
-- 4. Оптимизацию запросов, которые фильтруют или группируют по airplane_code -- Примечание: JOIN с таблицей routes (распределённой по route_no) может требовать motion.
DISTRIBUTED BY (airplane_code); DISTRIBUTED BY (airplane_code);
+1 -1
View File
@@ -15,7 +15,7 @@ BEGIN
IF v_src_count = 0 THEN IF v_src_count = 0 THEN
RAISE EXCEPTION RAISE EXCEPTION
'В источнике airplanes_ext нет строк.'; 'В источнике airplanes_ext нет строк. Проверьте: bookings-db запущен, PXF работает, STG DDL применён (bookings_stg_ddl или make ddl-gp).';
END IF; END IF;
-- Считаем строки, реально вставленные в stg.airplanes в этом батче -- Считаем строки, реально вставленные в stg.airplanes в этом батче
+2 -2
View File
@@ -36,6 +36,6 @@ WITH (appendonly=true, orientation=row, compresstype=zlib, compresslevel=1)
-- Обоснование: airport_code — это уникальный идентификатор аэропорта. -- Обоснование: airport_code — это уникальный идентификатор аэропорта.
-- Использование airport_code обеспечивает: -- Использование airport_code обеспечивает:
-- 1. Равномерное распределение данных по сегментам (airport_code имеет высокую кардинальность) -- 1. Равномерное распределение данных по сегментам (airport_code имеет высокую кардинальность)
-- 2. Co-location данных airports и routes при JOIN по departure_airport/arrival_airport -- 2. Оптимизацию запросов, которые фильтруют или группируют по airport_code
-- 3. Оптимизацию запросов, которые фильтруют или группируют по airport_code -- Примечание: JOIN с таблицей routes (распределённой по route_no) может требовать motion.
DISTRIBUTED BY (airport_code); DISTRIBUTED BY (airport_code);
+1 -1
View File
@@ -15,7 +15,7 @@ BEGIN
IF v_src_count = 0 THEN IF v_src_count = 0 THEN
RAISE EXCEPTION RAISE EXCEPTION
'В источнике airports_ext нет строк.'; 'В источнике airports_ext нет строк. Проверьте: bookings-db запущен, PXF работает, STG DDL применён (bookings_stg_ddl или make ddl-gp).';
END IF; END IF;
-- Считаем строки, реально вставленные в stg.airports в этом батче -- Считаем строки, реально вставленные в stg.airports в этом батче
+1 -1
View File
@@ -32,7 +32,7 @@ WITH (appendonly=true, orientation=row, compresstype=zlib, compresslevel=1)
-- Ключ распределения: ticket_no -- Ключ распределения: ticket_no
-- Обоснование: ticket_no — это основной бизнес-ключ для билетов. -- Обоснование: ticket_no — это основной бизнес-ключ для билетов.
-- Использование ticket_no обеспечивает: -- Использование ticket_no обеспечивает:
-- 1. Co-location данных boarding_passes и segments при JOIN по ticket_no -- 1. Коллокацию данных boarding_passes и segments при JOIN по ticket_no
-- 2. Равномерное распределение данных по сегментам (ticket_no имеет высокую кардинальность) -- 2. Равномерное распределение данных по сегментам (ticket_no имеет высокую кардинальность)
-- Примечание: stg.tickets распределена по book_ref, поэтому JOIN boarding_passes ↔ tickets по ticket_no может требовать motion. -- Примечание: stg.tickets распределена по book_ref, поэтому JOIN boarding_passes ↔ tickets по ticket_no может требовать motion.
DISTRIBUTED BY (ticket_no); DISTRIBUTED BY (ticket_no);
+1 -2
View File
@@ -29,7 +29,6 @@ WITH (appendonly=true, orientation=row, compresstype=zlib, compresslevel=1)
-- Обоснование: book_ref — это уникальный идентификатор бронирования. -- Обоснование: book_ref — это уникальный идентификатор бронирования.
-- Использование book_ref обеспечивает: -- Использование book_ref обеспечивает:
-- 1. Равномерное распределение данных по сегментам (book_ref имеет высокую кардинальность) -- 1. Равномерное распределение данных по сегментам (book_ref имеет высокую кардинальность)
-- 2. Co-location данных bookings и tickets при JOIN по book_ref -- 2. Коллокацию данных bookings и tickets при JOIN по book_ref
-- 3. Оптимизацию запросов, которые фильтруют или группируют по book_ref -- 3. Оптимизацию запросов, которые фильтруют или группируют по book_ref
DISTRIBUTED BY (book_ref); DISTRIBUTED BY (book_ref);
+1 -1
View File
@@ -17,7 +17,7 @@ BEGIN
IF v_src_count = 0 THEN IF v_src_count = 0 THEN
RAISE EXCEPTION RAISE EXCEPTION
'В источнике routes_ext нет строк.'; 'В источнике routes_ext нет строк. Проверьте: bookings-db запущен, PXF работает, STG DDL применён (bookings_stg_ddl или make ddl-gp).';
END IF; END IF;
-- Считаем строки, реально вставленные в stg.routes в этом батче -- Считаем строки, реально вставленные в stg.routes в этом батче
+2 -5
View File
@@ -26,9 +26,6 @@ CREATE TABLE IF NOT EXISTS stg.seats (
) )
WITH (appendonly=true, orientation=row, compresstype=zlib, compresslevel=1) WITH (appendonly=true, orientation=row, compresstype=zlib, compresslevel=1)
-- Ключ распределения: airplane_code -- Ключ распределения: airplane_code
-- Обоснование: airplane_code обеспечивает co-location с таблицей airplanes. -- Обоснование: airplane_code обеспечивает коллокацию seats ↔ airplanes при JOIN по airplane_code
-- Использование airplane_code обеспечивает: -- (в MPP это уменьшает вероятность перераспределения данных / motion).
-- 1. Co-location данных seats и airplanes при JOIN по airplane_code
-- 2. Группировка мест по самолётам (в одном самолёте обычно много мест)
-- 3. Оптимизацию запросов, которые фильтруют или группируют по airplane_code
DISTRIBUTED BY (airplane_code); DISTRIBUTED BY (airplane_code);
+1 -1
View File
@@ -16,7 +16,7 @@ BEGIN
IF v_src_count = 0 THEN IF v_src_count = 0 THEN
RAISE EXCEPTION RAISE EXCEPTION
'В источнике seats_ext нет строк.'; 'В источнике seats_ext нет строк. Проверьте: bookings-db запущен, PXF работает, STG DDL применён (bookings_stg_ddl или make ddl-gp).';
END IF; END IF;
-- Считаем строки, реально вставленные в stg.seats в этом батче -- Считаем строки, реально вставленные в stg.seats в этом батче
+1 -1
View File
@@ -30,7 +30,7 @@ WITH (appendonly=true, orientation=row, compresstype=zlib, compresslevel=1)
-- Ключ распределения: ticket_no -- Ключ распределения: ticket_no
-- Обоснование: ticket_no — это основной бизнес-ключ для билетов. -- Обоснование: ticket_no — это основной бизнес-ключ для билетов.
-- Использование ticket_no обеспечивает: -- Использование ticket_no обеспечивает:
-- 1. Co-location данных segments и boarding_passes при JOIN по ticket_no -- 1. Коллокацию данных segments и boarding_passes при JOIN по ticket_no
-- 2. Равномерное распределение данных по сегментам (ticket_no имеет высокую кардинальность) -- 2. Равномерное распределение данных по сегментам (ticket_no имеет высокую кардинальность)
-- Примечание: stg.tickets распределена по book_ref, поэтому JOIN segments ↔ tickets по ticket_no может требовать motion. -- Примечание: stg.tickets распределена по book_ref, поэтому JOIN segments ↔ tickets по ticket_no может требовать motion.
DISTRIBUTED BY (ticket_no); DISTRIBUTED BY (ticket_no);
+1 -2
View File
@@ -32,8 +32,7 @@ WITH (appendonly=true, orientation=row, compresstype=zlib, compresslevel=1)
-- Ключ распределения: book_ref -- Ключ распределения: book_ref
-- Обоснование: book_ref — это основной бизнес-ключ для бронирований. -- Обоснование: book_ref — это основной бизнес-ключ для бронирований.
-- Использование book_ref обеспечивает: -- Использование book_ref обеспечивает:
-- 1. Co-location данных tickets и bookings при JOIN по book_ref -- 1. Коллокацию данных tickets и bookings при JOIN по book_ref
-- 2. Равномерное распределение данных по сегментам (book_ref имеет высокую кардинальность) -- 2. Равномерное распределение данных по сегментам (book_ref имеет высокую кардинальность)
-- 3. Оптимизацию запросов, которые фильтруют или группируют по book_ref -- 3. Оптимизацию запросов, которые фильтруют или группируют по book_ref
DISTRIBUTED BY (book_ref); DISTRIBUTED BY (book_ref);