Привет, Хабр!
Всем хорош Data Vault, однако схватиться с ним «врукопашную», используя только SQL, захочет не каждый. Останавливает большой объем ручных операций, а также большой объем деталей реализации. Большое количество join, за которые критикуют Data Vault, не является определяющим моментом, так как уже сейчас базы данных способны их эффективно обрабатывать, а с течением времени мощность серверов только возрастает.
Но творческая мысль не дремлет, постепенно появляются инструменты для автоматизации построения Data Vault. Например, это пакет AutomateDV для dbt, графическая надстройка над ним Datapulse, построение модели DV в BI.Qube.
Data Vault меня заинтересовал — уж много плюшек он сулит, и для его изучения я занимаюсь проектом asapBI — low‑code IDE для моделирования DWH. Требования к создаваемой системе я описал на сайте asapbi.ru. Их достаточно много, поэтому не буду их тут перечислять.
Сегодня я хотел поделиться графическим интерфейсом для создания хабов, линков и стеллитов. Критика приветствуется и очень желательна:‑)
Внешний вид IDE asapBI
asapBI реализован как плагин к VSCode или Theia:
Слева - дерево с базами данных (NORD, ASGARD, ...), схемами (repo_md, repo_fi), каталогами (ODS, DDS...), таблицами (sales_raw) и хабами (new_hub77, sales_hub...). За работу с базами отвечает модуль генерации SQL - для каждой базы он свой. Пока поддерживается только Greenplum.
Задача: создать в схеме FI новую папку, в ней 2 хаба с сателлитами, а затем связать хабы с помощью линка. Диаграмма будет выглядеть так:
1. Создание папки
При наведении мыши на схему или существующую папку можно создать новую:
Система при создании спрашивает, в какой пакет этот объект записать. Пакет потом поедет по ландшафту в тест, и далее в прод. Но мы не собираемся переносить этот объект, поэтому оставляем как есть:
Папка создана, можно закрывать мастер:
2. Создание хабов
Аналогично создаем первый хаб - Продукт
На второй страничке мастера ничего не меняем — хаб временный:
После сохранения хаб появляется в дереве объектов.
Нажатие на кнопку "Open object" закрывает мастер и открывает хаб на редактирование.
Выполненный при создании хаба DDL-запрос имеет следующий вид (комментарии к колонкам удалены, чтобы не замыливать):
CREATE TABLE repo_fi.product_demo_hub (
date_load date DEFAULT now() NOT NULL, -- Дата загрузки
src_sys text DEFAULT ''::character varying NOT NULL, -- Система - источник
hkey int8 GENERATED BY DEFAULT AS IDENTITY
( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807
START 1 CACHE 20 NO CYCLE) NOT NULL, -- Ключ хаба
CONSTRAINT product_demo_hub_pkey PRIMARY KEY (hkey)
)
USING heap
DISTRIBUTED REPLICATED;
COMMENT ON TABLE repo_fi.product_demo_hub IS '{ "app": "asapBI",
"descr": "Product Demo hub",
"type": "HUB",
"folder": "161"
}';
Ничего не мешает вручную, например, в DBeaver, выполнить этот код, и хаб точно так же появится в дереве объектов
Для просмотра всех полей удобно поставить чекбокс «Показывать служебные поля». По умолчанию они скрыты, чтобы не размывать фокус внимания.
При наведении мыши на узел хаба справа появляются три кнопки:
Кнопки по порядку:
Создание поля (бизнес-ключа);
Создание сателлита;
Создание линка.
Используя первые две кнопки «Создание поля» и «Создание сателлита», формируем хаб «Продукт» и сателлит:
При сохранении хаба и сателлита формируется следующий DDL-код:
ALTER TABLE repo_fi.product_demo_hub DROP CONSTRAINT product_demo_hub_unique;
ALTER TABLE repo_fi.product_demo_hub ADD product text;
COMMENT ON COLUMN repo_fi.product_demo_hub.product IS 'Продукт';
ALTER TABLE repo_fi.product_demo_hub ADD CONSTRAINT
product_demo_hub_unique UNIQUE ( product );
CREATE TABLE repo_fi.product_demo_hub_sat1 (
id bigint GENERATED BY DEFAULT AS IDENTITY primary key,
hkey bigint NOT NULL,
valid_from date DEFAULT now() NOT NULL,
date_load date DEFAULT now() NOT NULL,
src_sys text DEFAULT ''::character varying NOT NULL,
brand text, --Брэнд
categ text, --Категория продукта
FOREIGN KEY (hkey) REFERENCES repo_fi.product_demo_hub (hkey)
)
USING heap
DISTRIBUTED REPLICATED;
COMMENT ON TABLE repo_fi.product_demo_hub_sat1 IS '{ "app": "asapBI",
"descr": "New sat",
"type": "SAT",
"owner": "repo_fi.product_demo_hub"
}';
ALTER TABLE repo_fi.product_demo_hub_sat1 ADD CONSTRAINT
product_demo_hub_sat1_unique UNIQUE (hkey, valid_from);
Тру олд-скул программисты могут выполнить этот SQL напрямую в базе данных и результат будет тем же самым - в дереве появится хаб и сателлит.
Аналогично создаем новый хаб "Покупатель", на это раз без сателлита, но с линком:

При необходимости к линку можно добавить сателлиты (выделенная кнопка +Sat).
DDL при создании хаба:
CREATE TABLE repo_fi.customer_demo_hub (
date_load date DEFAULT now() NOT NULL, -- Дата загрузки
src_sys text DEFAULT ''::character varying NOT NULL, -- Система - источник
hkey int8 GENERATED BY DEFAULT AS IDENTITY
( INCREMENT BY 1 MINVALUE 1 MAXVALUE 9223372036854775807
START 1 CACHE 20 NO CYCLE) NOT NULL, -- Ключ хаба
customer text NULL, -- Покупатель
CONSTRAINT customer_demo_hub_pkey PRIMARY KEY (hkey),
CONSTRAINT customer_demo_hub_unique UNIQUE (customer)
)
USING heap
DISTRIBUTED REPLICATED;
COMMENT ON TABLE repo_fi.customer_demo_hub IS '{ "app": "asapBI",
"descr": "Customer Demo hub",
"type": "HUB",
"folder": "161"
}';
Добавление к хабу поля и линка генерирует такой DDL:
ALTER TABLE repo_fi.customer_demo_hub DROP CONSTRAINT customer_demo_hub_unique;
ALTER TABLE repo_fi.customer_demo_hub ADD customer text;
COMMENT ON COLUMN repo_fi.customer_demo_hub.customer IS 'Покупатель';
ALTER TABLE repo_fi.customer_demo_hub
ADD CONSTRAINT customer_demo_hub_unique
UNIQUE ( customer );
CREATE TABLE repo_fi.customer_demo_hub_link1 (
id bigint GENERATED BY DEFAULT AS IDENTITY primary key,
customer_demo_hub bigint,
date_load date DEFAULT now() NOT NULL,
src_sys text DEFAULT ''::character varying NOT NULL,
product_demo_hub bigint ,
FOREIGN KEY (customer_demo_hub) REFERENCES repo_fi.customer_demo_hub (hkey),
FOREIGN KEY (product_demo_hub) REFERENCES repo_fi.product_demo_hub (hkey)
)
USING heap
DISTRIBUTED REPLICATED;
COMMENT ON TABLE repo_fi.customer_demo_hub_link1 IS '{ "app": "asapBI",
"descr": "New link",
"type": "LINK"
}';
ALTER TABLE repo_fi.customer_demo_hub_link1
ADD CONSTRAINT customer_demo_hub_link1_unique
UNIQUE (customer_demo_hub, product_demo_hub);
Результат в папке DEMO:
два хаба, один с сателлитом
один линк на оба хаба, представлен в дереве ниже как под первым хабом, так и под вторым.
Что дальше?
А дальше — загружаем данные в созданную модель, но это уже тема другой публикации...