# Часть 13. Инкременты, snapshots и история История данных — один из главных источников скрытого смыслового дрейфа. Таблица может быть корректной «на сегодня», но непригодной для аудита, если вчерашнее состояние нельзя восстановить. В банковском контексте это особенно важно: отчёты, согласия, просрочка и риск-флаги должны быть воспроизводимы. ## Три режима истории 1. **Full refresh** — пересобрать всё из источников. Хорошо для учебного примера, плохо для больших боевых таблиц. 2. **Incremental model** — добавлять или обновлять изменившиеся строки. Требует стратегии, уникального ключа и политики переигрывания. 3. **Snapshot** — хранить изменение атрибутов во времени. Полезно для статусов, сегментов, состояния согласия и медленно меняющихся измерений. В учебном примере мы не усложняем все модели incremental-логикой, но должны понимать, где она появится в боевом контуре. ## Что писать в спецификации Для модели с историей спецификация должна отвечать: - какой ключ определяет строку; - какое поле определяет время события или изменения; - можно ли пересчитать прошлое; - что делать при поздно пришедших данных; - какая команда доказывает безопасность переигрывания. Плохая формулировка: ```markdown Сделать инкрементальную загрузку. ``` Хорошая: ```markdown Модель использует `transaction_id` как уникальный ключ и `transaction_date` как дату события. Поздние строки внутри 7 дней могут обновлять агрегаты. Более старые исправления требуют PatchSpec и подтверждения ревьюера. ``` ## Проверочные факты Минимальные факты: - повторный `dbt build` не меняет результат без изменения raw; - уникальный ключ не дублируется; - дата события не `null`; - окно переигрывания описано; - ревьюер вручную подтвердил, что семантика истории не изменилась. ## Qwen-запрос ```text Прочитай specs и marts. Найди модели, где нужна история, incremental strategy или snapshot. Для каждой верни ключ, дату события, политику переигрывания и открытые вопросы. SQL не меняй. ``` ## Минимальный выход После главы создайте заметку: ```markdown # Политика истории ## Атрибуты клиентов ## Карточные операции ## Кредиты ## Open API consents ## Переигрывание и поздние данные ``` Если модель не исторична, явно напишите почему. ## Разбор для читателя История данных кажется технической темой, пока не возникает вопрос «что мы знали на тот момент?». Для отчётности и риска это критично. Сегодняшний пересчёт может дать правильную текущую таблицу, но неправильный исторический ответ. Если вчера согласие было активно, а сегодня отозвано, простая перезапись состояния уничтожит важный факт. Инкрементальная модель, snapshot и full refresh — это не просто способы записать таблицу. Это разные обещания о времени. Full refresh говорит: пересобираем текущее состояние из источника. Incremental model говорит: добавляем или обновляем изменившиеся строки по ключу и окну переигрывания. Snapshot говорит: сохраняем изменение атрибута во времени. Выбор между ними должен быть записан до реализации, иначе агент выберет самый удобный вариант. Особенно опасны поздно пришедшие данные. Если операция за прошлую неделю пришла сегодня, можно ли менять уже построенные агрегаты? Если можно, за какой период? Если нельзя, где фиксируется исключение? Такие вопросы нельзя решать внутри `is_incremental()` по вдохновению. Они относятся к контракту, потому что меняют воспроизводимость результата. Учебный пример не обязан реализовать все режимы истории. Но читатель должен научиться видеть, где история понадобится в боевом контуре. Для клиентов это атрибуты и сегменты. Для платежей — время операции и поздние поступления. Для согласий — активность и отзыв. Для кредита — stage и просрочка. Хорошая спецификация хотя бы называет эти границы, даже если первая версия остаётся простым full refresh. ## Практика Выберите один источник и решите, нужен ли ему full refresh, incremental model или snapshot. Запишите ключ, дату события, политику переигрывания и что делать с поздними данными. ## Типичная ошибка Думать, что `materialized='incremental'` решает историю. Это только режим записи. Смысл истории задают ключи, временные метки, политика переигрывания и факты ревьюера. ## Контрольные вопросы 1. Чем incremental model отличается от snapshot? 2. Какие факты доказывают безопасность переигрывания? 3. Почему поздно пришедшие данные нужно описывать до SQL?