docs(course): каркас курса и переобвязка уроков 0–6 на путь import (#21)
Зачем: после редизайна пути менти курс ссылался на старый путь generated-history-analytics/backfill и не проходился по новому стенду. Что: в README курса — единый блок подготовки и канонического сброса (make clean -> make up + ddl_init/world_init -> make superset-init), таблица уроков дополнена лабами 07–08 («в работе»); LESSON_STANDARD и уроки 0–6 ссылаются на канонический блок; урок 1 переведён на дозаливку через world_next_day (кнопкой-анонсом, цена в минутах названа); урок 4 — лесенка DAG-ов; урок 5 — словарь «база import / живой поток»; урок 6 обязателен; цифры старого мира помечены маркером «сверить-на-стенде». Проверка: grep по generated-history-analytics/backfill в docs/course/ пуст; правки только в docs/course/; git diff --check чистый. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -84,19 +84,12 @@ ODS мы пересобираем целиком, одной задачей Airf
|
||||
|
||||
## 2. Руки: смотрим базовый прогон
|
||||
|
||||
Поднимаем стенд и создаём стартовую историю. Это штатный путь курса: готовый источник
|
||||
данных стенда пишет события в Kafka, ClickHouse читает их в STG, затем batch строит
|
||||
ODS, DDS и DM. Файлы `data/*.jsonl` пока остаются только кладовкой значений для этого
|
||||
источника, а не источником аналитического контура.
|
||||
Подготовь стенд по
|
||||
[канонической инструкции курса](../README.md#подготовка-и-канонический-сброс).
|
||||
После успешного `world_init` эталонный мир уже прошёл путь Kafka → STG → ODS → DDS → DM.
|
||||
|
||||
```bash
|
||||
make generated-history-analytics
|
||||
make up
|
||||
```
|
||||
|
||||
Команда прогоняет всю цепочку слоёв и прямо в консоли печатает то, что нам нужно сейчас, —
|
||||
блок **«Статистика ODS»**. Это просто счётчики строк по всем восьми таблицам слоя (четыре
|
||||
основных и четыре с ошибками). Пример формы вывода:
|
||||
Ниже — форма блока **«Статистика ODS»**, который печатает `make transform`. Это просто
|
||||
счётчики строк по всем восьми таблицам слоя (четыре основных и четыре с ошибками):
|
||||
|
||||
```
|
||||
Статистика ODS:
|
||||
@@ -111,12 +104,14 @@ make up
|
||||
│ ods.geo_by_click_errors │ 0 │
|
||||
└────────────────────────────┴──────┘
|
||||
```
|
||||
<!-- сверить-на-стенде -->
|
||||
|
||||
Прочитаем эту табличку — в ней три вещи, которые стоит заметить.
|
||||
|
||||
**Все четыре `*_errors` — по нулям.** Значит, стартовая история чистая: ни одна запись не дала
|
||||
ошибки разбора, столбец `parse_errors` у всех пустой. Это нормально — данные стенда аккуратные.
|
||||
Ошибки мы увидим в секции 4, когда сами их устроим.
|
||||
<!-- сверить-на-стенде -->
|
||||
|
||||
**`browser` и `location` идут в одном зерне события.** Сколько событий пришло, столько строк
|
||||
и ожидаем увидеть после типизации, если ключи валидны.
|
||||
@@ -254,6 +249,7 @@ ORDER BY (click_id)
|
||||
её через `toFloat64OrNull` — «привести к дробному числу». Заменим тип на целочисленный —
|
||||
`toInt64OrNull`, «привести к целому». Для строки `"50.82709"` целого числа не получится
|
||||
(там точка, дробная часть), и функция вернёт `NULL`. То есть широта просто исчезнет.
|
||||
<!-- сверить-на-стенде -->
|
||||
|
||||
Из секции 3 помним: разбор продублирован, поэтому правок будет **две** — в обоих `INSERT`
|
||||
блока `GEO EVENTS`. Открой `sql/ods/20_stg_to_ods.sql`, найди оба вхождения и в каждом замени
|
||||
@@ -293,6 +289,7 @@ LIMIT 4;
|
||||
│ 9ffd819b-... │ ᴺᵁᴸᴸ │ 85.37752 │ ['bad_geo_latitude'] │
|
||||
└──────────────┴──────────────┴───────────────┴──────────────────────┘
|
||||
```
|
||||
<!-- сверить-на-стенде -->
|
||||
|
||||
Вот теперь видно всё разом — и DQ-split, и «двойной учёт» из секции 3 вживую. Строки с валидным
|
||||
`click_id` остались в основной таблице с пометкой `bad_geo_latitude`. И те же записи попали в
|
||||
@@ -307,6 +304,7 @@ LIMIT 4;
|
||||
> это молча срезало миллисекунды, и время по всему стенду уехало в `1970-01-21`. Ничто на это
|
||||
> не указывало — поймали только прогоном на стенде. Мораль урока: тип выбирают осознанно, даже
|
||||
> когда функция «не падает».
|
||||
<!-- сверить-на-стенде -->
|
||||
|
||||
**Верни как было.** Откати обе правки — верни `toFloat64OrNull` в оба места. Если запутался,
|
||||
проще одной командой откатить весь файл к версии из репозитория:
|
||||
@@ -316,8 +314,10 @@ git checkout -- sql/ods/20_stg_to_ods.sql
|
||||
make transform
|
||||
```
|
||||
|
||||
После этого `geo_by_click_errors` снова `0`, широта на месте. А если стенд совсем «поплыл» —
|
||||
всегда есть полный чистый прогон: `make generated-history-analytics && make up`.
|
||||
После этого `geo_by_click_errors` снова `0`, широта на месте. А если стенд совсем
|
||||
«поплыл», пройди
|
||||
[канонический сброс](../README.md#подготовка-и-канонический-сброс).
|
||||
<!-- сверить-на-стенде -->
|
||||
|
||||
---
|
||||
|
||||
@@ -329,6 +329,7 @@ make transform
|
||||
| почему `device`/`geo` меньше событий | запрос `uniqExact(click_id)` по `stg.geo_raw` | число различных `click_id` совпадает с `ods.geo_by_click` |
|
||||
| правка из секции 4 | блок «Статистика ODS» | `ods.geo_by_click_errors` прыгнул с `0` на ненулевое число |
|
||||
| правка из секции 4 | `SELECT geo_latitude, parse_errors FROM ods.geo_by_click` | широта `NULL`, в `parse_errors` — `bad_geo_latitude` |
|
||||
<!-- сверить-на-стенде -->
|
||||
|
||||
---
|
||||
|
||||
@@ -339,6 +340,7 @@ make transform
|
||||
- скрин блока «Статистика ODS», где после правки `ods.geo_by_click_errors` ушёл с `0`
|
||||
на ненулевое число;
|
||||
- либо выборка из `ods.geo_by_click` с пустой широтой и меткой `bad_geo_latitude` рядом.
|
||||
<!-- сверить-на-стенде -->
|
||||
|
||||
И проверь себя на словах — примерно эти вопросы всплывут на еженедельном созвоне:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user