Data Vault 2.0 deep dive на собеседовании Data Engineer
payments(user_id) и refunds(user_id). Нужно получить пользователей, у которых был платёж, но не было ни одного возврата. Какой запрос корректнее всего описывает задачу?Содержание:
Эта статья — про продвинутый Data Vault 2.0, а не про азы. Предполагается, что вы уже знаете, что такое hub (бизнес-ключ), link (связь между ключами) и satellite (описательные атрибуты с историей). Если нет — начните с базовой статьи Data Vault 2.0 для DE, а сюда возвращайтесь за глубиной: слои архитектуры, hash-ключи, таблицы-ускорители запросов (PIT и bridge) и ghost-записи. Именно эти темы отделяют кандидата, который «читал про DV», от того, кто его строил.
Три слоя: Raw, Business, Information Mart
Data Vault 2.0 — это не только моделирование, но и слоистая архитектура хранилища. На собесе часто просят объяснить, зачем нужны три слоя и что в каждом можно, а что нельзя.
Raw Vault — прямая загрузка из источников. Данные грузятся как есть, без применения бизнес-правил: только структурируются в hub, link и satellite. Ключевой принцип — insert-only (только вставка, без UPDATE и DELETE). Каждая загрузка добавляет новые строки, старые не трогаются. Это даёт полную аудитируемость: видно, что и когда пришло из источника, и хранилище можно воспроизвести на любую дату.
Business Vault — производный слой с вычисленными структурами и мягкими бизнес-правилами (soft rules). Здесь считают то, чего нет в источнике напрямую: агрегаты, дедупликацию, приведение к единой бизнес-логике, вычисляемые сателлиты. Сюда же обычно относят таблицы-ускорители запросов — PIT и bridge. Важно: жёсткие правила (hard rules), которые могут изменить или потерять данные, в Raw Vault не применяют — их место здесь.
Information Mart — витрина под потребление: денормализованная схема (обычно star schema), готовая для BI. Часто это вьюхи поверх Raw и Business Vault, а не отдельные физические таблицы. Именно на этот слой ходят аналитики и дашборды.
Смысл разделения — у каждого слоя своя ответственность: Raw хранит правду источника, Business применяет логику, Mart отдаёт данные пользователю. Меняется бизнес-правило — переписываете Business Vault, не трогая сырьё.
Hash-ключи и hashdiff
Главное отличие DV2.0 от DV1.0 — переход с последовательных суррогатных ключей на hash-ключи. Ключ считается как хеш от бизнес-ключа, и это даёт две вещи: детерминированность (одинаковый бизнес-ключ всегда даёт один и тот же hash на любой системе) и возможность грузить hub, link и satellite параллельно, не дожидаясь генерации суррогатных ключей и не делая lookup. На MPP-платформах это критично для скорости загрузки.
hub_customer:
customer_hk = MD5(customer_id) -- hash-ключ = хеш бизнес-ключа
customer_id -- сам бизнес-ключ
load_dt -- когда запись загружена
record_source -- откуда пришлаHashdiff — хеш от всех описательных атрибутов сателлита. Нужен, чтобы понять, изменилась ли запись, без сравнения колонка за колонкой. При загрузке считаете hashdiff новой версии и сравниваете с последним для этого ключа: совпал — данные те же, ничего не вставляем; отличается — появилась новая версия, добавляем строку.
sat_customer:
customer_hk
load_dt
hashdiff = MD5(name || email || phone) -- изменился → новая версия записи
name, email, phoneНа собесе про хеши любят копать: какой алгоритм брать. MD5 исторически стандарт (компактный, быстрый), но у него есть риск коллизий, поэтому на больших объёмах и там, где важна безопасность, берут SHA-256. Ещё частый вопрос — как считать hashdiff консистентно: приводить значения к строке единообразно, обрабатывать NULL (например, заменять на пустую строку или специальный маркер) и использовать разделитель между полями, чтобы ('ab','c') и ('a','bc') не давали одинаковый хеш.
Point-in-Time таблицы
У одного hub может быть много сателлитов, и каждый обновляется в свои моменты времени. Чтобы получить состояние сущности «как было на дату T», пришлось бы join'ить все сателлиты с коррелированными подзапросами «возьми последнюю версию до T» — это медленно и уродливо.
PIT-таблица (Point-in-Time) решает это: заранее просчитывает для каждого бизнес-ключа на каждую снимок-дату, какая именно версия (load_dt) каждого сателлита была актуальна в тот момент. Это таблица-ускоритель из Business Vault: сами данные она не хранит, только указатели на нужные версии сателлитов.
CREATE TABLE pit_customer (
customer_hk, -- ключ сущности
snapshot_dt, -- дата снимка
sat_personal_dt, -- какая версия sat_personal актуальна на snapshot_dt
sat_address_dt, -- какая версия sat_address
sat_account_dt -- какая версия sat_account
);После этого запрос состояния на дату превращается в простые equi-join'ы: берёте строку PIT на нужную дату и джойните сателлиты по паре (customer_hk, load_dt). Никаких подзапросов «найди максимум» — отсюда и скорость.
Bridge-таблицы
Bridge-таблица — второй тип ускорителя запросов. Она заранее просчитывает пути обхода через несколько hub и link, чтобы не делать множество join'ов на лету при работе со связями «многие ко многим».
Когда сущности связаны цепочкой (клиент → заказ → товар → категория), навигация по нескольким link на каждом запросе стоит дорого. Bridge собирает нужные комбинации ключей в одну таблицу, часто с предагрегацией по путям, и запрос вместо десятка join'ов делает один-два. Как и PIT, bridge живёт в Business Vault и периодически пересчитывается снапшотами.
Ghost- и unknown-записи
Для части ключей в сателлите может не быть записей: данные ещё не пришли или неприменимы. Тогда процесс загрузки вставляет специальную ghost-запись — заглушку с хеш-ключом из одних нулей и дефолтной датой (например, 1900-01-01).
ghost-запись в сателлите:
customer_hk = '00000000000000000000000000000000'
load_dt = '1900-01-01'
hashdiff = '00000000000000000000000000000000'
name = 'Unknown', email = 'Unknown', ...Зачем это нужно. Во-первых, PIT и bridge могут ссылаться на ghost-запись, и тогда join к сателлиту всегда что-то находит — outer join превращается в inner, без NULL и без пропущенных строк. Во-вторых, в витринах ghost играет роль «unknown / not applicable» для внешнего ключа: аналитик видит явное «Неизвестно» вместо пустоты, а COUNT и GROUP BY не ломаются на NULL. Иногда различают zero key (запись ещё не приехала) и ghost record (осознанная заглушка-плейсхолдер), но идея одна — избавиться от NULL-join'ов и упростить запросы.
Частые ошибки
- Применять бизнес-правила в Raw Vault. Raw должен хранить правду источника insert-only. Любая трансформация, которая может исказить или потерять данные, — это hard rule, ей место в Business Vault. Иначе теряется аудитируемость.
- Считать hashdiff без учёта NULL и разделителя. Без единого маркера для NULL и разделителя между полями конкатенация даёт ложные совпадения или ложные изменения — история сателлита едет.
- Игнорировать риск коллизий MD5. На собесе почти всегда спрашивают про выбор алгоритма. Ответ «всегда MD5» без упоминания коллизий и альтернативы SHA-256 звучит поверхностно.
- Путать PIT и bridge с хранением данных. Это ускорители запросов, а не источник истины: они только указывают на версии и пути, их всегда можно пересчитать из Raw/Business Vault.
- Забывать про ghost-записи и получать NULL-join'ы. Без заглушек PIT/bridge при отсутствующем сателлите дают NULL, запросы усложняются, а агрегаты искажаются.
Связанные темы
- Data Vault 2.0 для DE
- SCD типы для DE
- Inmon vs Kimball для DE
- Star schema vs Snowflake для DE
- Подготовка к собесу Data Engineer
FAQ
Зачем в DV2.0 hash-ключи вместо суррогатных?
Hash-ключ детерминирован: одинаковый бизнес-ключ даёт один и тот же хеш на любой системе, без централизованной генерации последовательности. Это позволяет грузить hub, link и satellite параллельно и независимо, без lookup суррогатного ключа, что критично для скорости на MPP-платформах.
Чем PIT-таблица отличается от bridge?
PIT ускоряет запрос состояния одной сущности «на дату»: для каждого ключа и снимок-даты хранит указатели на актуальные версии её сателлитов. Bridge ускоряет навигацию между несколькими hub и link (связи «многие ко многим»), заранее просчитывая пути обхода. Обе — ускорители запросов в Business Vault, обе можно пересчитать.
MD5 или SHA-256 для хешей?
MD5 компактнее и быстрее, поэтому исторически стандарт в DV. Но у MD5 есть риск коллизий, поэтому на больших объёмах и там, где важна устойчивость к коллизиям, берут SHA-256 — ценой большего размера ключа. Правильный ответ на собесе — назвать trade-off, а не одну опцию.
Что такое ghost-запись и зачем она нужна?
Это заглушка в сателлите с хеш-ключом из нулей и дефолтной датой. Она позволяет PIT и bridge всегда находить строку в сателлите (outer join становится inner, без NULL) и служит значением «unknown / not applicable» в витринах, чтобы агрегаты и группировки не ломались на NULL.
Можно ли применять бизнес-логику прямо в Raw Vault?
Нет. Raw Vault грузится insert-only и хранит данные как есть, чтобы сохранить полную аудитируемость и воспроизводимость. Все вычисления, дедупликацию и приведение к единой бизнес-логике выносят в Business Vault, а витрины строят уже поверх обоих слоёв.
Это официальная информация?
Нет. Статья основана на методологии Data Vault 2.0 Дэна Линштедта, публичной документации и опыте инженеров. Конкретные реализации в компаниях отличаются деталями.
Тренируйте Data Engineering — откройте тренажёр с 1500+ вопросами для собесов.