Van Raw Vault tot Business Vault — bouw een schaalbare, auditeerbare data architectuur met Hub, Link en Satellite tabellen, dbt integratie en bewezen loading patterns.
Data Vault 2.0 is een modelleringsmethodologie ontwikkeld door Dan Linstedt in de jaren 90, formeel gepubliceerd in 2000 en uitgebreid naar versie 2.0 in 2013. De methodologie combineert elementen van derde normaalvorm (3NF) en ster-schema's om een flexibele, auditeerbare en schaalbare data architectuur te creëren voor enterprise data warehouses.
De filosofie van Data Vault is gebaseerd op drie kernprincipes: agility (bronwijzigingen veroorzaken minimale impact), auditability (elke record is volledig herleidbaar naar de bron) en scalability (parallelle loading zonder bottlenecks).
| Kenmerk | 3NF (Inmon) | Ster-schema (Kimball) | Data Vault 2.0 |
|---|---|---|---|
| Primair doel | OLTP, integratie | Rapportage, analyse | Enterprise DWH, staging |
| Historiekopslag | Beperkt | Via SCD | Ingebouwd (altijd insert) |
| Flexibiliteit bij bronwijzigingen | Laag | Gemiddeld | Hoog |
| Auditeerbaarheid | Gemiddeld | Laag | Volledig |
| Leercurve | Laag | Laag | Hoog |
| Queryperformance direct | Matig | Hoog | Laag (via Information Mart) |
| Laag | Doel | Inhoud |
|---|---|---|
| Raw Vault | As-is opslag van bronsystemen | Hubs, Links, Satellites — ongewijzigde brondata |
| Business Vault | Berekende en afgeleide data | Computed Satellites, Derived Links, Same-As Links |
| Information Mart | Rapportage en analyse | Ster-schema's, flat tables, views voor BI tools |
Data Vault bestaat uit drie fundamentele entiteittypes. Elke tabel heeft een specifiek doel en een vaste structuur. Het begrijpen van deze drie typen is de basis van elke Data Vault implementatie.
Een Hub slaat de unieke business sleutels op van een kernentiteit (bijv. Klant, Product, Order). Een Hub bevat géén beschrijvende attributen — alleen de business key en metadata. Elke business key komt precies één keer voor in de Hub.
| Kolom | Type | Verplicht | Beschrijving |
|---|---|---|---|
klant_hk | CHAR(32) | VERPLICHT | Hash key — MD5/SHA hash van de business key |
klant_bk | VARCHAR(255) | VERPLICHT | Business key uit het bronsysteem |
load_dts | TIMESTAMP | VERPLICHT | Laadtijdstip — wanneer de record voor het eerst gezien |
rec_src | VARCHAR(100) | VERPLICHT | Record source — welk bronsysteem de data leverde |
-- Hub: unieke business sleutels voor Klant CREATE TABLE raw_vault.hub_klant ( klant_hk CHAR(32) NOT NULL, -- MD5 hash van klant_bk klant_bk VARCHAR(255) NOT NULL, -- bijv. 'KLANT-00123' load_dts TIMESTAMP NOT NULL, -- eerste keer gezien rec_src VARCHAR(100) NOT NULL, -- bijv. 'CRM_SALESFORCE' CONSTRAINT pk_hub_klant PRIMARY KEY (klant_hk) ); -- Insert: alleen nieuwe business keys laden INSERT INTO raw_vault.hub_klant (klant_hk, klant_bk, load_dts, rec_src) SELECT DISTINCT MD5(UPPER(TRIM(klant_id))) AS klant_hk, klant_id AS klant_bk, CURRENT_TIMESTAMP AS load_dts, 'CRM_SALESFORCE' AS rec_src FROM staging.stg_klant WHERE NOT EXISTS ( SELECT 1 FROM raw_vault.hub_klant h WHERE h.klant_hk = MD5(UPPER(TRIM(stg_klant.klant_id))) );
Een Link legt de relatie vast tussen twee of meer Hubs. Links zijn immutable: eens aangemaakt worden ze nooit gewijzigd. Een Link bevat de hash keys van de betrokken Hubs en metadata.
-- Link: relatie tussen Bestelling en Klant CREATE TABLE raw_vault.lnk_bestelling_klant ( bestelling_klant_hk CHAR(32) NOT NULL, -- hash van bestelling_hk + klant_hk bestelling_hk CHAR(32) NOT NULL, -- FK naar hub_bestelling klant_hk CHAR(32) NOT NULL, -- FK naar hub_klant load_dts TIMESTAMP NOT NULL, rec_src VARCHAR(100) NOT NULL, CONSTRAINT pk_lnk_bestelling_klant PRIMARY KEY (bestelling_klant_hk), CONSTRAINT fk_lnk_bk_bestelling FOREIGN KEY (bestelling_hk) REFERENCES raw_vault.hub_bestelling(bestelling_hk), CONSTRAINT fk_lnk_bk_klant FOREIGN KEY (klant_hk) REFERENCES raw_vault.hub_klant(klant_hk) ); -- Hash key berekening: concatenatie van betrokken hub keys SELECT MD5(bestelling_hk || '|' || klant_hk) AS bestelling_klant_hk FROM staging.stg_bestelling;
Een Satellite slaat alle beschrijvende attributen op van een Hub of Link, inclusief volledige historiek. Elke wijziging in attributen leidt tot een nieuwe rij (insert-only). De hash_diff kolom detecteert of een record daadwerkelijk gewijzigd is.
-- Satellite: attributen van Klant met volledige historiek CREATE TABLE raw_vault.sat_klant_details ( klant_hk CHAR(32) NOT NULL, -- FK naar hub_klant load_dts TIMESTAMP NOT NULL, -- tijdstip van deze versie load_end_dts TIMESTAMP, -- NULL = huidig record hash_diff CHAR(32) NOT NULL, -- hash van alle attributen rec_src VARCHAR(100) NOT NULL, -- Business attributen klant_naam VARCHAR(200), email VARCHAR(254), telefoonnummer VARCHAR(20), segment VARCHAR(50), stad VARCHAR(100), land CHAR(2), CONSTRAINT pk_sat_klant_details PRIMARY KEY (klant_hk, load_dts), CONSTRAINT fk_sat_kd_klant FOREIGN KEY (klant_hk) REFERENCES raw_vault.hub_klant(klant_hk) ); -- Hash diff: detecteer wijzigingen (laad alleen als hash_diff verschilt) INSERT INTO raw_vault.sat_klant_details SELECT MD5(UPPER(TRIM(klant_id))) AS klant_hk, CURRENT_TIMESTAMP AS load_dts, NULL AS load_end_dts, MD5(klant_naam || email || segment || stad) AS hash_diff, 'CRM_SALESFORCE' AS rec_src, klant_naam, email, telefoonnummer, segment, stad, land FROM staging.stg_klant s WHERE NOT EXISTS ( SELECT 1 FROM raw_vault.sat_klant_details sat WHERE sat.klant_hk = MD5(UPPER(TRIM(s.klant_id))) AND sat.hash_diff = MD5(s.klant_naam || s.email || s.segment || s.stad) AND sat.load_end_dts IS NULL );
Een PIT-tabel is een hulpstructuur die de meest recente Satellite records op elk gewenst tijdstip bijhoudt. PIT tabellen verbeteren de queryperformance enorm bij het samenvoegen van meerdere Satellites.
-- Point-in-Time tabel voor Klant CREATE TABLE raw_vault.pit_klant ( klant_hk CHAR(32) NOT NULL, snapshot_dts TIMESTAMP NOT NULL, -- het peilmoment sat_klant_details_dts TIMESTAMP, -- actuele load_dts in SAT_KLANT_DETAILS sat_klant_contact_dts TIMESTAMP, -- actuele load_dts in SAT_KLANT_CONTACT CONSTRAINT pk_pit_klant PRIMARY KEY (klant_hk, snapshot_dts) );
Consistente naamgeving is in Data Vault extra belangrijk omdat de architectuur veel tabellen genereert. Stel conventies vast voordat het project start en documenteer ze in een Data Dictionary.
| Prefix | Type | Voorbeeld |
|---|---|---|
HUB_ | Hub tabel | HUB_KLANT, HUB_PRODUCT, HUB_ORDER |
LNK_ | Link tabel | LNK_BESTELLING_KLANT, LNK_ORDER_PRODUCT |
SAT_ | Satellite tabel | SAT_KLANT_DETAILS, SAT_KLANT_CONTACT |
PIT_ | Point-in-Time tabel | PIT_KLANT, PIT_PRODUCT |
BV_ | Business Vault object | BV_SAT_KLANT_SCORE, BV_LNK_KLANT_MERGED |
SAL_ | Same-As Link | SAL_KLANT_DEDUPLICATIE |
EFF_ | Effectivity Satellite | EFF_LNK_BESTELLING_KLANT |
STG_ | Staging tabel | STG_KLANT, STG_ORDER |
Hash keys worden berekend uit de genormaliseerde business key. De keuze van het hash-algoritme heeft impact op performance en botsingsrisico.
| Algoritme | Output | Botsingsrisico | Performance | Aanbeveling |
|---|---|---|---|---|
| MD5 | 32 hex chars | Theoretisch (verwaarloosbaar) | Snel | Geschikt voor de meeste projecten |
| SHA-1 | 40 hex chars | Laag | Gemiddeld | Verouderd, vermijd voor nieuw werk |
| SHA-256 | 64 hex chars | Extreem laag | Langzamer | Bij hoge compliance-eisen |
-- Regel 1: Trim spaties, uppercase, NULL behandeling MD5(UPPER(TRIM(COALESCE(klant_id, '-1')))) -- Regel 2: Samengestelde sleutels — gebruik scheidingsteken MD5( UPPER(TRIM(land_code)) || '||' || UPPER(TRIM(klant_id)) ) -- Regel 3: Hash diff voor Satellites MD5( COALESCE(klant_naam, '') || '||' || COALESCE(email, '') || '||' || COALESCE(segment, '') || '||' || COALESCE(stad, '') ) -- Alternatief met SHA-256 (PostgreSQL) ENCODE(SHA256(CONVERT_TO(UPPER(TRIM(klant_id)), 'UTF8')), 'hex')
| Kolom | Type | Aanwezig in | Beschrijving |
|---|---|---|---|
load_dts | TIMESTAMP NOT NULL | Hub, Link, Satellite | Tijdstip van eerste/huidige load |
load_end_dts | TIMESTAMP NULL | Satellite | Eindtijdstip versie; NULL = huidig |
rec_src | VARCHAR(100) NOT NULL | Hub, Link, Satellite | Bronsysteem identificatie |
hash_diff | CHAR(32) NOT NULL | Satellite | Hash van alle attributen, voor change detectie |
tenant_id | VARCHAR(50) | Alle tabellen | Multi-tenant ondersteuning (optioneel) |
'-1' of 'UNKNOWN') als de business key NULL kan zijn. Een NULL in een hash key zorgt voor niet-aaneensluitende records in de Hub en onvindbare Links.
De scheiding tussen Raw Vault en Business Vault is een van de meest belangrijke architectuurprincipes van Data Vault 2.0. Deze scheiding garandeert dat de originele brondata altijd ongewijzigd toegankelijk blijft.
De Raw Vault slaat brondata op precies zoals ontvangen van het bronsysteem. Geen transformaties, geen interpretaties, geen businessregels. Elke record is volledig herleidbaar tot een specifieke load uit een specifiek bronsysteem.
De Business Vault bevat data die is afgeleid uit de Raw Vault via businessregels en berekeningen. Business Vault objecten zijn duidelijk gelabeld (prefix BV_) en altijd reproduceerbaar vanuit de Raw Vault.
-- Computed Satellite: klant klantwaarde score berekend vanuit Raw Vault CREATE TABLE business_vault.bv_sat_klant_score ( klant_hk CHAR(32) NOT NULL, load_dts TIMESTAMP NOT NULL, load_end_dts TIMESTAMP, hash_diff CHAR(32) NOT NULL, rec_src VARCHAR(100) NOT NULL DEFAULT 'BUSINESS_RULE_KLANT_SCORE', -- Berekende attributen klant_score DECIMAL(5,2), klant_tier VARCHAR(20), -- 'BRONZE', 'SILVER', 'GOLD', 'PLATINUM' score_versie VARCHAR(10) DEFAULT 'v2.1', CONSTRAINT pk_bv_sat_klant_score PRIMARY KEY (klant_hk, load_dts) ); -- Vul Business Vault met berekende score op basis van omzetdata INSERT INTO business_vault.bv_sat_klant_score SELECT h.klant_hk, CURRENT_TIMESTAMP AS load_dts, NULL AS load_end_dts, MD5(CAST(SUM(f.omzet) AS VARCHAR)) AS hash_diff, 'BUSINESS_RULE_KLANT_SCORE' AS rec_src, ROUND(SUM(f.omzet) / 1000.0, 2) AS klant_score, CASE WHEN SUM(f.omzet) > 100000 THEN 'PLATINUM' WHEN SUM(f.omzet) > 50000 THEN 'GOLD' WHEN SUM(f.omzet) > 10000 THEN 'SILVER' ELSE 'BRONZE' END AS klant_tier, 'v2.1' AS score_versie FROM raw_vault.hub_klant h JOIN raw_vault.lnk_bestelling_klant lbk ON h.klant_hk = lbk.klant_hk JOIN raw_vault.sat_bestelling_financieel f ON lbk.bestelling_hk = f.bestelling_hk WHERE f.load_end_dts IS NULL GROUP BY h.klant_hk;
Een Same-As Link legt vast dat twee business keys in de Hub dezelfde echte entiteit vertegenwoordigen. Dit is de Data Vault manier voor deduplicatie en entiteitsresolutie — zonder de Raw Vault aan te passen.
-- SAL: twee klant records die dezelfde persoon zijn CREATE TABLE business_vault.sal_klant_dedup ( sal_hk CHAR(32) NOT NULL, -- hash van master_hk + duplicate_hk master_klant_hk CHAR(32) NOT NULL, -- de 'winnende' Hub record dupl_klant_hk CHAR(32) NOT NULL, -- de duplicaat Hub record load_dts TIMESTAMP NOT NULL, rec_src VARCHAR(100) NOT NULL, -- bijv. 'MDM_DEDUP_PROCESS' match_methode VARCHAR(50), -- 'FUZZY_NAME', 'EMAIL_MATCH', etc. match_score DECIMAL(5,4), CONSTRAINT pk_sal_klant_dedup PRIMARY KEY (sal_hk) );
Een Effectivity Satellite houdt bij wanneer een Link-relatie actief of inactief is. Dit is nodig omdat Links zelf immutable zijn — je verwijdert een Link nooit, maar registreert de inactiviteit in een aparte Satellite.
-- Effectivity Satellite: is de klant-bestelling relatie nog actief? CREATE TABLE raw_vault.eff_lnk_bestelling_klant ( bestelling_klant_hk CHAR(32) NOT NULL, -- FK naar lnk_bestelling_klant load_dts TIMESTAMP NOT NULL, load_end_dts TIMESTAMP, rec_src VARCHAR(100) NOT NULL, is_actief BOOLEAN NOT NULL DEFAULT TRUE, CONSTRAINT pk_eff_lnk_bk PRIMARY KEY (bestelling_klant_hk, load_dts) );
raw_vault en business_vault). Zo is altijd duidelijk welke data ongewijzigde brondata is en welke data via businessregels is berekend.
dbt (data build tool) is de standaard tool voor het bouwen van Data Vault pipelines in moderne data stacks. dbt biedt versiebeheert SQL transformaties, maakt testen eenvoudig en ondersteunt incrementeel laden out-of-the-box.
dbt_project/ ├── models/ │ ├── staging/ # Staging laag — brondata normaliseren │ │ ├── crm/ │ │ │ ├── stg_klant.sql │ │ │ └── stg_bestelling.sql │ │ └── erp/ │ │ └── stg_factuur.sql │ ├── raw_vault/ # Raw Vault — Hubs, Links, Satellites │ │ ├── hubs/ │ │ │ ├── hub_klant.sql │ │ │ └── hub_product.sql │ │ ├── links/ │ │ │ └── lnk_bestelling_klant.sql │ │ └── satellites/ │ │ ├── sat_klant_details.sql │ │ └── sat_klant_contact.sql │ ├── business_vault/ # Business Vault — berekende objecten │ │ ├── bv_sat_klant_score.sql │ │ └── sal_klant_dedup.sql │ └── information_mart/ # Informatiemarts — ster-schema voor BI │ ├── dim_klant.sql │ └── fct_omzet.sql ├── macros/ │ ├── hash_key.sql # Hash key berekening macro │ └── hash_diff.sql # Hash diff berekening macro └── tests/ ├── generic/ └── singular/
{% macro hash_key(columns, alias='hash_key') %}
{#- Berekent MD5 hash van één of meer kolommen -#}
MD5(
{% for col in columns %}
UPPER(TRIM(COALESCE({{ col }}::VARCHAR, '-1')))
{% if not loop.last %} || '||' || {% endif %}
{% endfor %}
) AS {{ alias }}
{% endmacro %}
{% macro hash_diff(columns, alias='hash_diff') %}
{#- Berekent MD5 hash van alle Satellite attributen -#}
MD5(
{% for col in columns %}
COALESCE({{ col }}::VARCHAR, '')
{% if not loop.last %} || '||' || {% endif %}
{% endfor %}
) AS {{ alias }}
{% endmacro %}
{{
config(
materialized = 'incremental',
unique_key = 'klant_hk',
schema = 'raw_vault'
)
}}
WITH source AS (
SELECT * FROM {{ ref('stg_klant') }}
{% if is_incremental() %}
-- Alleen nieuwe records laden bij incrementele runs
WHERE _loaded_at > (SELECT MAX(load_dts) FROM {{ this }})
{% endif %}
),
hub AS (
SELECT
{{ hash_key(['klant_id'], 'klant_hk') }},
klant_id AS klant_bk,
CURRENT_TIMESTAMP AS load_dts,
rec_src
FROM source
QUALIFY ROW_NUMBER() OVER (PARTITION BY klant_id ORDER BY _loaded_at) = 1
)
SELECT * FROM hub
{{
config(
materialized = 'incremental',
unique_key = ['klant_hk', 'load_dts'],
schema = 'raw_vault'
)
}}
WITH source AS (
SELECT
{{ hash_key(['klant_id'], 'klant_hk') }},
{{ hash_diff(['klant_naam', 'email', 'segment', 'stad']) }},
CURRENT_TIMESTAMP AS load_dts,
NULL AS load_end_dts,
rec_src,
klant_naam, email, telefoonnummer, segment, stad, land
FROM {{ ref('stg_klant') }}
{% if is_incremental() %}
WHERE _loaded_at > (SELECT MAX(load_dts) FROM {{ this }})
{% endif %}
),
-- Verwijder records waarbij hash_diff niet is gewijzigd
gefilterd AS (
SELECT s.*
FROM source s
{% if is_incremental() %}
LEFT JOIN {{ this }} t
ON s.klant_hk = t.klant_hk
AND t.load_end_dts IS NULL
WHERE t.hash_diff IS NULL -- nieuw record
OR s.hash_diff != t.hash_diff -- gewijzigd record
{% endif %}
)
SELECT * FROM gefilterd
version: 2
models:
- name: hub_klant
description: "Hub met unieke business sleutels voor Klant"
columns:
- name: klant_hk
description: "MD5 hash van klant_bk"
tests:
- unique
- not_null
- name: klant_bk
tests:
- not_null
- name: load_dts
tests:
- not_null
- name: rec_src
tests:
- not_null
- name: sat_klant_details
columns:
- name: klant_hk
tests:
- not_null
- relationships:
to: ref('hub_klant')
field: klant_hk
- name: hash_diff
tests:
- not_null
Data Vault is ontworpen voor hoge-performante, parallelle loading. De juiste loading strategie is cruciaal voor schaalbaarheid en betrouwbaarheid van je pipeline.
| Strategie | Wanneer gebruiken | Voordelen | Nadelen |
|---|---|---|---|
| Full load | Initiële load, kleine bronsystemen | Eenvoudig, geen change detection nodig | Traag bij grote datasets |
| Incrementeel (timestamp) | Bronsysteem heeft updated_at kolom | Snel, efficiënt | Late arriving data gemist |
| Incrementeel (CDC) | Hoge frequentie, near-real-time | Minimale latency, volledig | Complexe setup (Debezium, Fivetran) |
| Hash vergelijking | Geen timestamp beschikbaar | Detecteert elke wijziging | Volledig scan vereist |
Een van de grootste voordelen van Data Vault is de mogelijkheid om Hubs, Links en Satellites parallel te laden. De volgorde is echter wel van belang vanwege foreign key afhankelijkheden.
# Fase 1: Staging (parallel per bron) staging: - stg_klant # CRM bron - stg_bestelling # Orders bron - stg_product # ERP bron # Fase 2: Hubs (alle hubs parallel) hubs: - hub_klant ↗ parallel - hub_bestelling ↗ parallel - hub_product ↗ parallel # Fase 3: Links (na Hubs — parallel onderling) links: - lnk_bestelling_klant ↗ parallel - lnk_bestelling_product ↗ parallel # Fase 4: Satellites (parallel na Hubs en Links) satellites: - sat_klant_details ↗ parallel - sat_klant_contact ↗ parallel - sat_bestelling_status ↗ parallel
Een Data Vault pipeline moet idempotent zijn: meerdere keren draaien met dezelfde brondata produceert altijd hetzelfde resultaat. Dit maakt herverwerking en foutenherstel veilig.
-- MERGE patroon (Snowflake/SQL Server/BigQuery) MERGE INTO raw_vault.hub_klant AS target USING ( SELECT DISTINCT MD5(UPPER(TRIM(klant_id))) AS klant_hk, klant_id AS klant_bk, CURRENT_TIMESTAMP AS load_dts, rec_src FROM staging.stg_klant ) AS source ON target.klant_hk = source.klant_hk WHEN NOT MATCHED THEN INSERT (klant_hk, klant_bk, load_dts, rec_src) VALUES (source.klant_hk, source.klant_bk, source.load_dts, source.rec_src); -- WHEN MATCHED: niets doen — Hub records zijn immutable! -- INSERT ... ON CONFLICT patroon (PostgreSQL) INSERT INTO raw_vault.hub_klant (klant_hk, klant_bk, load_dts, rec_src) SELECT DISTINCT MD5(UPPER(TRIM(klant_id))), klant_id, CURRENT_TIMESTAMP, rec_src FROM staging.stg_klant ON CONFLICT (klant_hk) DO NOTHING; -- Hub is immutable
load_audit) met tijdstip, aantal records, statusSAT_ERR_) voor records die niet geladen konden wordenrec_src altijd granulaar genoeg om terug te herleiden welke batch welke records bevatteload_dts, en de bijbehorende Satellites volgen automatisch. Pas wel op met PIT tabellen — die moeten gerecalculeerd worden na een late load.
De Data Vault zelf is niet direct geschikt voor rapportage — de complexe joins en historische structuur maken queries traag en moeilijk. De Information Mart is de rapportagelaag die gebouwd wordt bovenop de Data Vault, typisch als ster-schema of flat table.
Een dimensietabel in de Information Mart wordt gebouwd door de Hub samen te voegen met de meest recente Satellite records (via PIT tabel of directe join op load_end_dts IS NULL).
-- Dimensietabel: actuele klantgegevens (SCD Type 1 snapshot) CREATE OR REPLACE VIEW information_mart.dim_klant AS SELECT h.klant_hk AS klant_sk, -- surrogate key h.klant_bk AS klant_id, -- business key d.klant_naam, d.email, d.segment, d.stad, d.land, c.telefoonnummer, s.klant_score, s.klant_tier, h.load_dts AS eerste_gezien, d.load_dts AS details_bijgewerkt FROM raw_vault.hub_klant h -- Meest recente klantdetails LEFT JOIN raw_vault.sat_klant_details d ON d.klant_hk = h.klant_hk AND d.load_end_dts IS NULL -- Meest recente contactgegevens LEFT JOIN raw_vault.sat_klant_contact c ON c.klant_hk = h.klant_hk AND c.load_end_dts IS NULL -- Berekende scores vanuit Business Vault LEFT JOIN business_vault.bv_sat_klant_score s ON s.klant_hk = h.klant_hk AND s.load_end_dts IS NULL;
Een Bridge table is een precomputed join van meerdere Links en Hubs. Bridge tables maken complexe veel-op-veel relaties efficiënt querybaar vanuit de Information Mart zonder de volledige Data Vault structuur te doorlopen.
-- Bridge: klant → bestelling → product (voor omzetanalyse) CREATE TABLE information_mart.brg_klant_product ( snapshot_dts DATE NOT NULL, klant_hk CHAR(32) NOT NULL, bestelling_hk CHAR(32) NOT NULL, product_hk CHAR(32) NOT NULL, -- Gedriligeerde metrics voor snelle rapportage omzet DECIMAL(12,2), aantal INTEGER, CONSTRAINT pk_brg_klant_product PRIMARY KEY (snapshot_dts, klant_hk, bestelling_hk, product_hk) ); -- Vul Bridge table dagelijks INSERT INTO information_mart.brg_klant_product SELECT CURRENT_DATE AS snapshot_dts, lbk.klant_hk, lbk.bestelling_hk, lbp.product_hk, SUM(sbr.omzet) AS omzet, SUM(sbr.aantal) AS aantal FROM raw_vault.lnk_bestelling_klant lbk JOIN raw_vault.lnk_bestelling_product lbp ON lbk.bestelling_hk = lbp.bestelling_hk JOIN raw_vault.sat_bestelling_regel sbr ON sbr.bestelling_product_hk = lbp.bestelling_product_hk AND sbr.load_end_dts IS NULL GROUP BY lbk.klant_hk, lbk.bestelling_hk, lbp.product_hk;
De Information Mart volgt het Kimball ster-schema principe. Dimensies en feitentabellen worden gegenereerd vanuit de Data Vault objecten. Gebruikers van BI-tools (Power BI, Tableau, Looker) werken uitsluitend met de Information Mart — nooit direct met de Raw of Business Vault.
| Data Vault object | Information Mart object | Transformatie |
|---|---|---|
| Hub + actuele Satellites | Dimensietabel (dim_) | JOIN + SCD Type 1 of 2 |
| Link + metrische Satellites | Feitentabel (fct_) | JOIN + aggregatie |
| Bridge table | Feitentabel (fct_) | Directe mapping |
| PIT tabel + Satellites | Historische dimensie | Snapshot per datum |
| Business Vault Satellites | Berekende dimensiekolommen | Directe overname |
||)