Data Vault — одна из самых популярных и устоявшихся методологий моделирования архитектуры данных. Но в ситуации, когда на входе несколько десятков внутренних и внешних источников, а сверху прежней «снежинки» построены уже сотни бизнес-витрин, переход на Data Vault «на ходу» может оказаться затруднительным и ресурсозатратным. Поэтому мы в СберЗдоровье пошли другим путём.

Меня зовут Иван Гуляев. Я Senior DE с уклоном в архитектуру и моделирование данных в CберЗдоровье — MedTech-компании №1 в России. В этой статье я расскажу, как мы с помощью самописного приложения, каталога данных (Datahub) и связки dbt + Automate-dv построили Data Vault на Trino.
Немного о Data Vault, Data Governance, Datahub
Во многих компаниях после начального этапа бурного роста часто остаётся наследие в виде уже устоявшихся парадигм, принципов и архитектуры со времен, когда в приоритете было быстрое решение бизнес-задач. И зачастую это влечет типовые последствия:
архитектура, заложенная на начальном этапе, не заточена под дальнейшее масштабирование;
все домены живут в своём мире;
функционал аналитики требует всё больше усилий для дальнейшей модификации и развития, не говоря уже и о масштабировании с технической стороны.
Принцип решения этой проблемы универсален — нанять больше людей, закупить более мощное железо, переехать из Greenplum на Trino, используя популярный ныне подход с разделением storage и compute. Не менее важно — пересмотреть подход к моделированию и архитектуре данных. И здесь многие оправданно выбирают концепцию Data Vault, которая:
позволяет достаточно гибко подстраиваться под изменчивые исходные таблицы;
даёт возможность грузить данные по частям;
поддерживает историчность SCD-2 на таблицах-сателлитах из коробки;
имеет множество модификаций и расширений (Multi-active satellites, XTS, PIT и прочие).
Нюанс в том, что Data Vault внедряется без проблем только на ранних этапах развития ИТ в компании. Но когда в компании уже много разношерстных источников, на которых уже выстроена целая система с бизнес-отчетностью, процесс переезда на Data Vault начинает требовать выделенную MDM/EDW-команду, которая будет заниматься детективной и архитектурной работой:
распутывать все связи между данными из исходных таблиц-источников для построения линков;
выделять основные бизнес-сущности в хабы, проводя созвоны с бизнесом, пользователями, продакт-менеджерами, продуктовыми и бизнес-аналитиками;
продумывать архитектуру конечного решения (raw data vault, business data vault);
адаптировать текущие инструменты или изобретать новые для построения Data Vault.
Процесс весьма кропотливый и ресурсоёмкий, однако некоторые элементы можно облегчить и даже автоматизировать.
В такой ситуации невозможно переоценить важность развития подходов Data Governance в компании. Ведь именно благодаря Data Governance данные и аналитика становятся более прозрачными и контролируемыми, так как вся основная документация и метаданные из платформы данных лежат в вашем каталоге — например, в Datahub.
Datahub по своей сути полезен для всех пользователей:
аналитики могут оценить и изучить структуру исходных таблиц из источников, проставить теги и описания для таблиц и колонок;
инженеры — посмотреть Lineage из источника до Kafka и бизнес-витрин, оценить результаты тестов по качеству данных;
менеджеры — посмотреть на внутрянку таблиц в их домене.
И именно Datahub становится единым источником правды и метаданных: к серверу можно подключиться по протоколу GraphQL и получить практически любую нужную информацию про платформу данных.
Например, простой запрос, который покажет все внешние ключи и URN внешних таблиц, выглядит следующим образом:
query getDatasetSchema { dataset( urn: "urn:li:dataset:(urn:li:dataPlatform:mysql,my_source_db.my_source_table,PROD)" ) { urn name schemaMetadata { foreignKeys { name sourceFields { fieldPath } foreignFields { fieldPath } foreignDataset { urn } } } } }
Потенциально можно создать базу из таких запросов и построить свой персонализированный фронтенд для расширения функционала Datahub. Именно это мы частично и воплотили в Transform App.
Больше кейсов и новых решений нашей команды — в ТГ-канале SberHealth IT ;)
Выбор платформы для Data Vault
Одним из ключевых вопросов при внедрении Data Vault является выбор платформы для построения и определения алгоритма поставки данных в Data Vault из источников.
За основу мы взяли концепт CDC (Change Data Capture), который обеспечивается связкой «Debezium + Kafka-Connect»: с их помощью можно практически в реальном времени стримить данные в целевую платформу, минимизируя при этом нагрузку из БД-источников за счёт чтения из журнала транзакций (по сравнению с традиционным ETL по курсору).
В качестве целевой платформы подойдет любая DWH БД, которая может совладать с большим количеством JOIN'ов (без них в Data Vault не обойтись). Мы выбрали комбинацию Trino/S3/Iceberg — с учетом возможности горизонтального и вертикального масштабирования системы, эта связка является одной из самых производительных и гибких в современных реалиях.

Дальнейшие шаги в построении Data Vault: Automate-DV и первая версия Transform App в виде терминального приложения
В платформе данных СберЗдоровья используется dbt для трансформации данных и построения бизнес-витрин. Экосистема dbt бурно развивается, есть много различных плагинов и расширений: начиная от DQ-пакетов (dbt expectations, dbt project evaluator) и заканчивая полноценными фреймворками для построения Data Vault.
Одним из таких решений является Automate-DV — набор dbt-шаблонов, которые позволяют построить все основные сущности raw data vault слоя: stage, hub, links, satellites, refs, t-links и другие.
Код модели типа satellites выглядит следующим образом:
{{ config(materialized='incremental') }} {%- set yaml_metadata -%} source_model: 'v_stg_transactions' src_pk: 'TRANSACTION_HK' src_fk: - 'CUSTOMER_HK' - 'ORDER_HK' src_payload: - 'TRANSACTION_NUMBER' - 'TRANSACTION_DATE' - 'TYPE' - 'AMOUNT' src_eff: 'EFFECTIVE_FROM' src_ldts: 'LOAD_DATETIME' src_source: 'RECORD_SOURCE' {%- endset -%} {% set metadata_dict = fromyaml(yaml_metadata) %} {{ automate_dv.t_link(src_pk=metadata_dict["src_pk"], src_fk=metadata_dict["src_fk"], src_payload=metadata_dict["src_payload"], src_eff=metadata_dict["src_eff"], src_ldts=metadata_dict["src_ldts"], src_source=metadata_dict["src_source"], source_model=metadata_dict["source_model"]) }}
Примечательно, что из коробки нет поддержки Trino, но код открыт и его можно модифицировать: изменить поведение, добавить новые макросы или подвиды Data Vault сущностей и даже внедрить поддержку БД, которых нет изначально (что мы и сделали для Trino).
Фреймворк достаточно удобный, но не отвечает на вопрос, что делать, если на входе у вас сотни таблиц из разных источников. Безусловно, всегда можно заполнить вручную, но тогда вы рискуете инвестировать очень много времени, особенно если у вас большое количество таблиц.
Для решения этого вопроса команда наших дата-инженеров начала разработку Transformation Framework — CLI-приложения, которое позволяет подключиться к Datahub через GraphQL, загрузить метаданные нужной таблицы, проставить все главные и внешние ключи, кастомизировать название домена и другие параметры. На выходе из этого CLI-приложения мы получаем заполненные dbt-модели для Automate-DV.

Фунционально? Да.
Удобно ли пользоваться? Если выгружать таблицы точечно, то да, но большой батч таблиц придется грузить по одному, что в терминальном приложении делать не очень удобно.
Терминальное приложение было в проде несколько месяцев, и за это время мы перенесли с его помощью несколько доменов. Но у нас еще оставалось несколько точек роста, которые можно было реализовать. Например:
повысить наглядность;
улучшить автоматизацию редактирования уже существующих моделей;
упростить построение навигации по CLI.
В результате было принято решение сделать приложение с полноценным UI-интерфейсом.
Переход на следующий этап: Transform App
Для разработки приложения под наши задачи мы взяли за основу React с библиотекой xyflow для отрисовки Canvas с ERD-таблиц. В результате получили функциональное и интуитивно понятное решение.
Алгоритм работы с ним довольно прост.
Для начала пользователь должен выбрать из Datahub (кстати, подключение по тому же GraphQL) таблицы, которые нужно перенести в Data Vault / в шаблоны Automate-DV:


При желании можно настроить алиас для схемы (если на бэкенде источник называется техническим именем, а загрузить нужно под бизнесовым), включить поддержку CDC: так Transform App сходит в Datahub и постарается найти загруженные таблички после CDC-пайплайна, чтобы подставить их в dbt'шный source.yml.
После выбора таблиц открывается основное приложение с канвасом и настройками Data Vault:

Здесь у пользователя есть следующие возможности:
добавить связи между таблицами, если их нет в БД источнике;
выключить связи между таблицами, которые есть в БД источнике (например, если есть chat_messages и колонка reply_id ссылается на id в этой же таблице)
выключить генерацию хабов/сателлитов для определенных таблиц;
выбрать совсем другой тип сущности Data Vault — T-Link, Ref — которые не потребуется разбивать на основную связку из хаба/линка/сателлита.
Отобразить можно хоть все таблицы, правда в текущей реализации reactflow будет проседать по FPS при 50+ таблиц сразу.
Примечание: Здесь есть пространство для оптимизации: есть смысл оценить альтернативные библиотеки, вроде cytoscape или даже либы с поддержкой WebGL для отрисовки нод на GPU.
После нажатия на кнопку «Сгенерировать» получаем готовые для Automate-DV dbt файлы, которые можно из коробки сразу вставить в проект и материализовать.

Так же генерируются сопутствующие .yml файлы с метаданными и базовыми тестами (описания колонок тоже выгружаются из Datahub, если есть):

Полученные результаты и планы на будущее
Разработанное нами приложение уже выведено в продакшен для переноса таблиц-источников и моделирования Data Vault таблиц. Пользоваться таким канвасом в разы проще и нагляднее: если предыдущее решение подразумевало ручной ввод названий таблиц, то здесь можно выбрать сразу несколько (или даже все) таблиц из схемы-источника и быстро поменять тип сущности, отредактировать связи, настроить технические поля. В итоге то, что требовало раньше несколько часов, сейчас можно сделать за несколько минут и с лучшим качеством.
Безусловно, текущую систему можно (и нужно) дорабатывать. Так, например, в будущем мы планируем:
записывать метаданные из приложения в Custom Properties в Datahub, чтобы хранить кастомные связи, виды дата-волта и прочие метаданные в отдельном поле; ()
добавить возможность дробить таблицы на несколько хабов/линков/сателлитов, либо же наоборот — объединять в один хаб (частично это уже можно сделать, выключив хаб в настройках конкретной таблицы и оставив сателлит);
добавить другие виды сущностей Data Vault;
сделать полноценный онбординг при первом открытии с обучением пользователя базовым понятиям Data Vault;
добавить подсказки ИИ для нахождения связей на основе метаданных загруженных таблиц.
Однако даже в текущем формате Transform App уже значительно упрощает взаимодействие и построение Data Vault моделей. И дальше — больше. О том, что получится в итоге, обязательно расскажем в одной из следующих статей.
