docs(course): добавлен урок 2 (STG→ODS, типизация и DQ-split)
- Зачем:
- нужен учебный урок «руки» про типизацию слоя ODS и разделение
чистых/битых записей; по пути убрать мусор и неочевидности в
эталонном пути, чтобы он читался за один проход.
- Что:
- добавлен lessons/02_stg_to_ods.md по LESSON_STANDARD (6 секций,
режим «руки», эталон голоса — урок 1); регистр смягчён под уровень
«обзорно» с расшифровкой терминов (click-контекст, WITH, двойной учёт).
- 20_stg_to_ods.sql: поток данных в шапку + блок «DQ-split» (почему
строка может попасть и в основную таблицу, и в *_errors).
- 20_ods.sql: убран мусорный блок из 8 DROP TABLE mv_*_to_ods;
пояснено разное партиционирование (browser — по бизнес-дате,
click-контекст — по дате загрузки).
- Проверка:
- make ddl && make transform — проходят чисто, counts не изменились
(browser/location 50, device/geo 26 дедуп, *_errors 0).
- правка §4 (toFloat64OrNull→toInt64OrNull для geo_latitude) на стенде
даёт geo_by_click_errors 0→50 и NULL-широту с флагом bad_geo_latitude.
This commit is contained in:
+4
-13
@@ -9,21 +9,9 @@
|
||||
--
|
||||
-- Важно:
|
||||
-- - Наполнение ODS выполняется batch-процессом из sql/ods/20_stg_to_ods.sql
|
||||
-- - Materialized View STG → ODS в target-state не используются
|
||||
-- (а не Materialized View, как в STG): батч ради наблюдаемости пересчёта
|
||||
-- ============================================================================
|
||||
|
||||
-- ----------------------------------------------------------------------------
|
||||
-- Удаляем legacy MV STG → ODS (если ранее были созданы)
|
||||
-- ----------------------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS stg.mv_browser_raw_to_ods;
|
||||
DROP TABLE IF EXISTS stg.mv_browser_raw_to_ods_errors;
|
||||
DROP TABLE IF EXISTS stg.mv_location_raw_to_ods;
|
||||
DROP TABLE IF EXISTS stg.mv_location_raw_to_ods_errors;
|
||||
DROP TABLE IF EXISTS stg.mv_device_raw_to_ods;
|
||||
DROP TABLE IF EXISTS stg.mv_device_raw_to_ods_errors;
|
||||
DROP TABLE IF EXISTS stg.mv_geo_raw_to_ods;
|
||||
DROP TABLE IF EXISTS stg.mv_geo_raw_to_ods_errors;
|
||||
|
||||
-- ============================================================================
|
||||
-- BROWSER EVENTS
|
||||
-- ============================================================================
|
||||
@@ -46,6 +34,8 @@ CREATE TABLE IF NOT EXISTS ods.browser_event
|
||||
parse_errors Array(LowCardinality(String)) -- Ошибки парсинга (если есть)
|
||||
)
|
||||
ENGINE = ReplacingMergeTree(src_ingest_ts)
|
||||
-- Партиционируем по бизнес-дате события: у browser_event есть собственное время (event_ts).
|
||||
-- У click-контекста ниже (location/device/geo) такого времени нет — там партиция по дате загрузки.
|
||||
PARTITION BY toYYYYMM(event_date)
|
||||
ORDER BY (event_id)
|
||||
SETTINGS allow_nullable_key = 1;
|
||||
@@ -87,6 +77,7 @@ CREATE TABLE IF NOT EXISTS ods.location_event
|
||||
parse_errors Array(LowCardinality(String))
|
||||
)
|
||||
ENGINE = ReplacingMergeTree(src_ingest_ts)
|
||||
-- По дате загрузки: у location нет собственного времени события (только время приёма в STG)
|
||||
PARTITION BY toYYYYMM(toDate(src_ingest_ts))
|
||||
ORDER BY (event_id)
|
||||
SETTINGS allow_nullable_key = 1;
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
-- ============================================================================
|
||||
-- Batch-трансформация: STG → ODS
|
||||
-- ============================================================================
|
||||
-- Поток данных:
|
||||
-- stg.*_raw → ods.* (валидный ключ) + ods.*_errors (любая ошибка)
|
||||
--
|
||||
-- Назначение:
|
||||
-- - Перенос типизации STG → ODS из Materialized View в управляемый batch
|
||||
-- - Полная пересборка ODS для прозрачного мониторинга в Airflow
|
||||
-- - Сохранение DQ-логики: parse_errors + отдельные *_errors таблицы
|
||||
--
|
||||
-- DQ-split (почему одна строка может попасть в оба места):
|
||||
-- - Основная таблица ods.* — строки с валидным КЛЮЧОМ (event_id / click_id).
|
||||
-- В ней допустимы parse_errors по НЕключевым полям — строка остаётся, но помечена.
|
||||
-- - Таблица ods.*_errors — копия строк с ЛЮБОЙ ошибкой парсинга (для разбора).
|
||||
-- Поэтому строка с валидным ключом, но битым неключевым полем, попадёт И туда, И туда.
|
||||
--
|
||||
-- Когда запускать:
|
||||
-- - В DAG etl_pipeline перед ODS → DDS
|
||||
-- - После загрузки очередного среза данных в Kafka/STG
|
||||
|
||||
Reference in New Issue
Block a user