Если загружать сведения из источника сразу в готовую таблицу для отчёта, технические детали и предметные правила смешаются. При сбое трудно понять, что именно пришло, где пропала строка и каким правилом получена сумма. Поэтому в DWH обычно разделяют приём, согласование и выдачу данных. Эти этапы называют слоями. Слой обозначает ответственность, а не обязательно отдельный сервер.
Краткая карта слоёв
| Область | Что в ней хранится | Пример объекта | Кто обычно читает |
|---|---|---|---|
| Источник | Состояние приложения или его события | Таблица событий в PostgreSQL, ответ внешнего API | Приложение и коннектор |
| Landing / raw | Полученные файлы и записи, происхождение поставки | Неизменённый JSON ответа API, дата приёма, идентификатор файла | Инженер и загрузчик |
| Staging | Разобранные поля и технически проверенные типы | Таблица с датой как timestamp, суммой как numeric, ошибками разбора отдельно | Преобразования |
| Ядро / core / DDS | Согласованные ключи, значения и нужная история | Общий идентификатор объекта, версии его признака | Разработчики витрин |
| Витрины / data marts | Удобные для конкретных вопросов факты, измерения или агрегаты | Число событий по дню, типу и статусу | Аналитик, BI, другие сервисы |
Это распространённая логика, но не стандарт имён. В одной команде raw означает буквально исходные байты, в другой — уже разобранную таблицу. Термин DDS (Detailed Data Store) часто используют для детального согласованного слоя, но в конкретной компании он может означать другое. При входе в проект просите схему и контракт каждой области, а не выводите устройство по названию каталога.
Приём: landing и raw
Landing — место, куда поступает поставка до её разбора: файл в объектном хранилище, сообщение из очереди, выгрузка API. Это может быть временная зона или архив входов. Инженеру полезно знать источник, время получения, имя файла или позицию потока и контрольную сумму. Тогда можно доказать, какой именно вход обработали.
Raw обычно сохраняет полученный набор достаточно близко к оригиналу, чтобы его можно было обработать повторно. Например, API прислал поля amount = "2500" и currency = "RUB". Не стоит сразу превращать это в «25 рублей» без подтверждённого правила единицы. Если контракт источника изменится, исходник позволит восстановить прежнюю интерпретацию.
Raw не означает «доступно всем». Там могут быть персональные данные, ошибки формата и дубли. Для этой области нужны сроки хранения, права доступа и правила удаления. Если исходные файлы нельзя сохранять по требованиям безопасности, фиксируют хотя бы пригодный для проверки журнал поставок и безопасный вариант входа.
Staging: подготовка формы
В staging разбирают технический формат: строковую дату превращают в timestamp, проверяют обязательные поля, отделяют записи с ошибками, отмечают дубли доставки. Здесь удобно сохранить связь с raw: идентификатор поставки и исходной записи. Тогда ошибку в готовой витрине можно проследить назад.
Staging распознаёт amount = 2500 как целое число. При согласовании определяют, в какой единице записана сумма и учтены ли скидки. Для этого нужны правила источника: тип integer описывает форму значения, а валюта и порядок расчёта — его смысл.
Не каждую ошибку нужно отбрасывать. Неверный timestamp можно отправить в отдельный набор исключений, чтобы источник исправил запись, а остальные данные продолжили путь. Важно видеть число входных, принятых и исключённых строк, иначе «успешная» загрузка может скрывать потерю части данных.
Ядро: общий смысл и история
Ядро связывает источники и предоставляет устойчивые сущности. Если две системы используют разные коды одного объекта, здесь вводят проверенное соответствие. Если источники передают разные часовые пояса, единицы или статусы, здесь задают общее представление. Изменяемые признаки хранят с версиями, когда этого требуют аналитические вопросы.
Нельзя механически считать один источник всегда главным. Для разных атрибутов авторитетными могут быть разные системы. Правило выбора фиксируют по каждому атрибуту. Конфликтующие значения иногда нужно сохранить и показать как конфликт, а не молча выбрать более позднее.
В некоторых архитектурах ядро нормализовано, в других построено как Data Vault или набор детальных аналитических таблиц. Конкретные модели разберём в следующем блоке. Общая задача ядра — сделать предметные правила явными и повторно используемыми.
Витрины: удобная выдача
Витрина предназначена для группы вопросов и имеет известное зерно: что означает одна строка. Например, одна строка может обозначать один день и одну категорию обращений. Если в ней есть количество обращений и число решённых в срок, определения обеих мер должны быть одинаковыми для всех дашбордов.
Витрина бывает детальной или агрегированной. Детальная таблица хранит отдельные события, а агрегат сокращает объём чтения за счёт заранее посчитанного результата. Агрегат удобен для отчёта по дням, но уже не ответит на вопрос об отдельном обращении. Поэтому витрина не заменяет всё ядро.
Поверх витрин иногда создают семантический слой — каталог показателей и допустимых разрезов для BI. Он удерживает единые формулы, но не восстанавливает данные, потерянные до витрины.
Почему витрины часто денормализуют
В аналитическом чтении удобно получить категорию, регион и нужные меры через короткий путь. Поэтому описания могут заранее присоединять к детальному набору или собирать в широкие измерения звезды. Такое намеренное повторение называют денормализацией. Оно сокращает число соединений и делает контракт витрины понятнее пользователю. Источник для пересчёта и правило обновления повторяющихся описаний при этом должны оставаться известны.
Витрина не обязана быть одной широкой таблицей: факты с измерениями и нормализованные части иерархии тоже могут обслуживать аналитические вопросы. Сначала фиксируют зерно и нужный исторический разрез, затем выбирают удобную форму. Добавить описание через связь один-ко-многим без правила отбора — значит размножить исходные строки, а не просто ускорить чтение.
ODS не обязан быть ещё одним слоем DWH
ODS (Operational Data Store) обычно обозначает объединённый и относительно свежий взгляд на операционные данные. Например, оперативный экран может показывать текущий статус объекта вместе с признаком из другой системы. Ему важнее свежесть, чем длинная аналитическая история. В некоторых проектах ODS помещают между staging и ядром, в других он живёт отдельно и отдаёт данные приложению. Название не задаёт единственную архитектуру.
Чтобы не перепутать ODS и DDS, спросите: служит ли набор текущим оперативным действиям или длительному воспроизводимому анализу? Какую историю он хранит? Какова допустимая задержка? Ответы важнее расположения прямоугольника на схеме.
Как проверить путь записи
На каждой границе полезны три числа: сколько записей получили, сколько передали дальше и почему остались исключения. Для данных, где важна сумма, сравнивают также контрольные суммы или агрегаты по ключевым разрезам. Если вход содержит 100 строк, а ядро 98, это может быть корректное удаление двух дублей. Но причина должна быть доступна для проверки. Если витрина объединяет два источника, сверка только общего итога недостаточна: неверное соответствие ключей может сохранить сумму и исказить распределение.
Именно такое разделение превращает набор таблиц в обслуживаемый конвейер: можно исправить правило, повторить преобразование из сохранённого входа и объяснить, где изменился результат.
Попробуйте на данных
В учебной базе stg_orders содержит версии заказов и повторы доставки. orders хранит одну текущую строку на заказ. Посмотрите на разницу до построения витрины:
SELECT count(*) AS staging_rows, count(DISTINCT order_id) AS order_keys
FROM stg_orders;Число строк больше числа ключей не обязательно ошибка: часть строк — разные версии. Задания отдельно находят точные повторы, выбирают последнюю версию и собирают небольшой результат для чтения.
За июньские загрузки найдите первые 20 пар order_id, updated_at, которые пришли больше одного раза. Верните также deliveries и отсортируйте по order_id, updated_at.