ms-ai-architect/skills/ms-ai-engineering/references/data-engineering/master-data-management-ai.md
Kjell Tore Guttormsen ddce43d8b2 feat(ms-ai-architect): Spor 1 — Port-1-substrat migrert på 4 ikke-advisor-skills (243 Source + 327 Type + 325 TOC + stale-verified poison fjernet) [skip-docs]
Steg 9 (R4): unified migrate-corpus.mjs --write over engineering/governance/
infrastructure/security. 327 filer mutert, verified=null, prosa byte-identisk
(fra første ## seksjon), advisor urørt (0 endringer).

To applier-fixes oppdaget under kjøring (TDD, RED→GREEN):
- insertHeaderFields: anker faller nå tilbake når en meta-linje selv passerer
  500B (2 filer pakket et avsnitt i **Status:** → Type/Source landet utenfor
  scan-vinduet, applierens post-write-assertion fanget + restaurerte).
- normalizeStaleVerified: fjerner nå ALLE stale non-date **Verified:** i
  500B-vinduet, inkl. stray body-dup rett under --- (9 mlops-genaiops-filer var
  ellers falskt "verified"/fresh, droppet fra worklist). Operatør-godkjent
  utvidelse av carve-out; kun stray metadata-linjer, aldri prosa.

test-transform-criterion: precondition oppdatert til post-migrasjons-sannhet
(fila bærer nå Source). Suite 728/728 grønn.
2026-07-04 10:19:11 +02:00

540 lines
19 KiB
Markdown

# Master Data Management for AI
**Last updated:** 2026-06-24
**Status:** GA
**Category:** Data Engineering for AI
**Type:** reference
**Source:** https://learn.microsoft.com/purview/data-governance-master-data-management
---
## Innhold
- [Introduksjon](#introduksjon)
- [Golden Record Creation and Reconciliation](#golden-record-creation-and-reconciliation)
- [Entity Resolution and Deduplication](#entity-resolution-and-deduplication)
- [MDM Integration with Dataverse](#mdm-integration-with-dataverse)
- [Reference Data Versioning](#reference-data-versioning)
- [Data Quality SLAs for MDM Entities](#data-quality-slas-for-mdm-entities)
- [Referanser](#referanser)
- [For Cosmo](#for-cosmo)
## Introduksjon
Master Data Management (MDM) skaper en enkelt kilde til sannhet for kritiske forretningsenheter som kunder, produkter, ansatte og lokasjoner. For AI-losninger er kvaliteten pa stamdata direkte avgjorede -- en ML-modell trent pa inkonsistente kundedata vil produsere upaalitelige prediksjoner, og en RAG-losning med dupliserte dokumenter vil gi motstridende svar.
Microsoft tilbyr MDM gjennom flere tjenester: Microsoft Purview for data governance og MDM-integrasjoner, Dataverse som operativt masterdatasystem for Dynamics 365 og Power Platform, og Azure-tjenester som Data Factory for datakvalitet og deduplisering. For AI-pipelines i Fabric er det kritisk a sikre at referansedata og enhetsmapping er konsistent pa tvers av domener.
For norsk offentlig sektor er MDM spesielt viktig: Folkeregisteret, Enhetsregisteret og Matrikkelen er eksempler pa nasjonale masterdatakilder. Integrasjon med disse via Digdir sine felleslosninger, kombinert med intern MDM i Dataverse eller Fabric, sikrer at AI-losninger opererer pa palitelig grunn.
---
## Golden Record Creation and Reconciliation
### Hva er en Golden Record?
En golden record er den autoritative, konsoliderte versjonen av en enhet som kombinerer data fra flere kilder:
```
Kilde A: {navn: "Ola Nordmann", epost: "ola@firma.no", tlf: null}
Kilde B: {navn: "O. Nordmann", epost: null, tlf: "+47 90000000"}
Kilde C: {navn: "Ola Nordmann", epost: "ola.nordmann@firma.no", tlf: "+47 90000000"}
Golden Record: {
navn: "Ola Nordmann", -- Mest komplett, hoyest tillit
epost: "ola.nordmann@firma.no", -- Fra kilde C (nyeste, mest komplett)
tlf: "+47 90000000", -- Fra kilde B/C (konsistent)
kilder: ["A", "B", "C"],
tillit_score: 0.95
}
```
### Survivorship-regler
| Regel | Beskrivelse | Eksempel |
|-------|-------------|---------|
| **Most Recent** | Nyeste verdi vinner | Sist oppdatert adresse |
| **Most Complete** | Mest utfylt felt vinner | Lengste navn-streng |
| **Most Trusted Source** | Autoritativ kilde vinner | Folkeregisteret > CRM |
| **Frequency** | Hyppigste verdi vinner | 3 av 4 kilder sier "Oslo" |
| **Manual Override** | Manuell beslutning | Datakurator velger |
### Implementering i Fabric
```python
from pyspark.sql import functions as F
from pyspark.sql.window import Window
def create_golden_records(sources: dict, entity_key: str, rules: dict):
"""
Opprett golden records fra flere kilder med survivorship-regler.
Args:
sources: Dict med {kildenavn: DataFrame}
entity_key: Nokkelkolonne for matching
rules: Dict med {kolonne: survivorship_regel}
"""
# 1. Kombiner alle kilder med kildemerking
combined = None
for source_name, df in sources.items():
tagged = df.withColumn("_source", F.lit(source_name)) \
.withColumn("_load_time", F.current_timestamp())
combined = combined.unionByName(tagged, allowMissingColumns=True) \
if combined else tagged
# 2. Dedupliser og velg vinnere per kolonne
golden = combined.groupBy(entity_key)
agg_exprs = []
for col_name, rule in rules.items():
if rule == "most_recent":
agg_exprs.append(
F.last(col_name, ignorenulls=True).alias(col_name)
)
elif rule == "most_complete":
agg_exprs.append(
F.max(F.when(F.col(col_name).isNotNull(), F.col(col_name)))
.alias(col_name)
)
elif rule == "most_trusted":
# Sorter etter kildeprioritering
agg_exprs.append(
F.first(col_name, ignorenulls=True).alias(col_name)
)
golden_df = golden.agg(*agg_exprs)
return golden_df
# Bruk
sources = {
"crm": df_crm,
"erp": df_erp,
"folkeregisteret": df_folkereg
}
rules = {
"full_name": "most_trusted", # Folkeregisteret prioritert
"address": "most_recent", # Siste oppdatering
"phone": "most_complete", # Mest utfylt
"organization_number": "most_trusted" # Enhetsregisteret
}
golden_customers = create_golden_records(sources, "person_id", rules)
```
---
## Entity Resolution and Deduplication
### Duplikatdeteksjon i Dataverse
Microsoft Dataverse har innebygd duplikatdeteksjon for aktive poster som kontoer og kontakter:
| Funksjon | Beskrivelse |
|----------|-------------|
| **Duplikatdeteksjonsregler** | Definer matchingkriterier per entitet |
| **Sanntidssjekk** | Sjekker ved opprettelse/oppdatering |
| **Bulk-deteksjon** | Kjor deteksjon pa eksisterende data |
| **Merge** | Kombiner duplikater med valg av primaer-post |
### Fuzzy Matching i Fabric
For mer avansert entity resolution i AI-pipelines:
```python
from pyspark.sql import functions as F
from pyspark.ml.feature import NGram, HashingTF, MinHashLSH
def fuzzy_match_entities(df, match_columns, threshold=0.7):
"""
Fuzzy matching med MinHash LSH for skalerbar deduplisering.
"""
# 1. Kombiner matchkolonner til en tekststreng
df = df.withColumn(
"match_text",
F.lower(F.concat_ws(" ", *match_columns))
)
# 2. Tokeniser til n-grams
df = df.withColumn(
"tokens",
F.split(F.col("match_text"), " ")
)
# 3. Hashing for dimensjonsreduksjon
hashingTF = HashingTF(inputCol="tokens", outputCol="features", numFeatures=1024)
df_hashed = hashingTF.transform(df)
# 4. MinHash LSH for approximate nearest neighbors
mh = MinHashLSH(inputCol="features", outputCol="hashes", numHashTables=5)
model = mh.fit(df_hashed)
# 5. Finn lignende par
similar_pairs = model.approxSimilarityJoin(
df_hashed, df_hashed, threshold, distCol="distance"
)
return similar_pairs.filter(F.col("datasetA.id") < F.col("datasetB.id"))
# Eksempel: Dedupliser organisasjoner
duplicates = fuzzy_match_entities(
df_organizations,
match_columns=["org_name", "address", "postal_code"],
threshold=0.3 # Lav avstand = hoy likhet
)
```
### Deterministic vs. Probabilistic Matching
| Tilnaerming | Bruksomrade | Presisjon | Recall |
|-------------|-------------|-----------|--------|
| **Deterministic** | Eksakt match pa unike IDer | Hoy | Lav |
| **Rule-based** | Kombinasjon av felt med toleranser | Moderat-hoy | Moderat |
| **Probabilistic** | Fuzzy matching med ML-modeller | Moderat | Hoy |
| **Hybrid** | Deterministic forst, deretter probabilistic | Hoy | Hoy |
```python
# Hybrid-tilnaerming
def hybrid_entity_resolution(df_source, df_reference):
"""
Trinn 1: Eksakt match pa organisasjonsnummer
Trinn 2: Fuzzy match pa navn + adresse for resterende
"""
# Trinn 1: Deterministic match
exact_matches = df_source.join(
df_reference,
df_source["org_number"] == df_reference["org_number"],
"inner"
)
unmatched = df_source.join(
df_reference,
df_source["org_number"] == df_reference["org_number"],
"left_anti"
)
# Trinn 2: Fuzzy match for umatchede
fuzzy_matches = fuzzy_match_entities(
unmatched.unionByName(df_reference, allowMissingColumns=True),
match_columns=["org_name", "address"],
threshold=0.4
)
return exact_matches, fuzzy_matches
```
---
## MDM Integration with Dataverse
### Dataverse som Master Data System
Dataverse fungerer som operativt masterdatasystem for Dynamics 365-apper:
```
+-------------------+ Service Bus +------------------+
| Dataverse |------ Queue ------->| Logic App |
| (Master Data) | | (Transform to |
| | | Canonical Model)|
| - Accounts | +--------+---------+
| - Contacts | |
| - Products | +--------v---------+
| - Addresses | | Service Bus Topic|
+-------------------+ | (Canonical Data) |
+--------+---------+
|
+--------v---------+
| Consumers: |
| - Fabric Lakehouse|
| - Azure SQL |
| - Power BI |
+------------------+
```
### Synkronisering mellom Dataverse og Fabric
```python
# Dataverse til Fabric via Azure Synapse Link
# Konfigureres i Power Platform Admin Center
# Alternativt: Dataverse connector i Fabric Data Pipeline
# Pipeline -> Copy Activity -> Source: Dataverse -> Sink: Lakehouse
# Eksempel: Les masterdata fra Dataverse via Spark
df_accounts = spark.read \
.format("com.microsoft.cdm") \
.option("entity", "account") \
.option("dataverseUrl", "https://org.crm.dynamics.com") \
.load()
# Opprett referansetabell i Lakehouse
df_accounts.select(
"accountid",
"name",
"address1_city",
"accountnumber",
"industrycode"
).write \
.format("delta") \
.mode("overwrite") \
.saveAsTable("lakehouse.default.ref_organizations")
```
### Duplikatdeteksjon i Dataverse
```
# Dataverse duplikatdeteksjonsregler:
#
# 1. Opprett regel i Power Platform Admin Center
# - Entitet: Account
# - Matchkriterier: accountname (fuzzy match)
# + address1_city (eksakt match)
#
# 2. Aktiver sanntidssjekk
# - Ved opprettelse av ny post
# - Ved oppdatering av eksisterende post
#
# 3. Bulk-deteksjon
# - Kjor pa eksisterende data
# - Planlegg regelmessig kjoring
```
---
## Reference Data Versioning
### Versjonerte referansetabeller
```python
# Implementer SCD Type 2 for referansedata i Fabric
from delta.tables import DeltaTable
def upsert_reference_data(ref_table_name, new_data_df, key_columns, tracked_columns):
"""
SCD Type 2 upsert for referansedata.
Bevarer historikk for endrede verdier.
"""
ref_table = DeltaTable.forName(spark, ref_table_name)
# Bygg match-betingelse
match_condition = " AND ".join(
[f"target.{col} = source.{col}" for col in key_columns]
)
# Bygg endringsbetingelse
change_condition = " OR ".join(
[f"target.{col} != source.{col}" for col in tracked_columns]
)
# Merk utgaatte rader og sett inn nye
ref_table.alias("target").merge(
new_data_df.alias("source"),
match_condition
).whenMatchedUpdate(
condition=change_condition,
set={
"is_current": F.lit(False),
"valid_to": F.current_timestamp()
}
).whenNotMatchedInsertAll().execute()
# Sett inn oppdaterte rader som nye
changed = new_data_df.alias("s").join(
ref_table.toDF().filter("is_current = false").alias("t"),
[F.col(f"s.{c}") == F.col(f"t.{c}") for c in key_columns],
"inner"
).select("s.*") \
.withColumn("is_current", F.lit(True)) \
.withColumn("valid_from", F.current_timestamp()) \
.withColumn("valid_to", F.lit(None).cast("timestamp"))
changed.write.format("delta").mode("append").saveAsTable(ref_table_name)
# Eksempel: Oppdater kommuner-referanse (relevant ved kommunesammenslaainger)
upsert_reference_data(
ref_table_name="lakehouse.default.ref_municipalities",
new_data_df=df_new_municipalities,
key_columns=["municipality_code"],
tracked_columns=["municipality_name", "county_code", "county_name"]
)
```
### Referansedata fra nasjonale registre
| Register | Eier | Bruksomrade for AI |
|----------|------|-------------------|
| **Folkeregisteret** | Skatteetaten | Personentiteter i NER, chatbots |
| **Enhetsregisteret** | Bronnoysundregistrene | Organisasjonsdata for bedriftsanalyse |
| **Matrikkelen** | Kartverket | Eiendomsdata for geospatial AI |
| **Sektor-/fagregistre** | Statlig sektoretat | Domenespesifikk data for AI-modeller |
| **Kommuneregisteret** | SSB | Geografisk referanse |
```python
# Eksempel: Last inn kommuneregister fra SSB API
import requests
import json
def load_ssb_municipality_register():
"""Last inn offisiell kommuneliste fra SSB."""
url = "https://data.ssb.no/api/klass/v1/classifications/131/codes"
params = {"from": "2026-01-01", "to": "2026-12-31"}
response = requests.get(url, params=params)
data = response.json()
# Konverter til Spark DataFrame
df = spark.createDataFrame([
{
"code": item["code"],
"name": item["name"],
"valid_from": item["validFrom"],
"valid_to": item.get("validTo")
}
for item in data["codes"]
])
return df
```
---
## Data Quality SLAs for MDM Entities
### Kvalitetsdimensjoner for masterdata
| Dimensjon | Definisjon | Malemetode | Eksempel SLA |
|-----------|-----------|------------|-------------|
| **Completeness** | Andel utfylte felt | % ikke-null verdier | >= 98% |
| **Uniqueness** | Ingen duplikater | Antall duplikater / totalt | = 100% |
| **Accuracy** | Korrekthet mot kilde | Stikkprovekontroll | >= 99% |
| **Timeliness** | Ferskhet pa data | Tid siden siste oppdatering | < 24 timer |
| **Consistency** | Samsvar mellom systemer | Cross-system validering | >= 99.5% |
| **Validity** | Overholder forretningsregler | Regelvalidering | >= 99% |
### Implementere DQ-SLAer i Fabric
```python
from datetime import datetime, timedelta
def check_mdm_quality_slas(table_name: str, slas: dict) -> dict:
"""
Sjekk datakvalitet mot definerte SLAer for en MDM-tabell.
"""
df = spark.table(table_name)
total_rows = df.count()
results = {}
# Completeness
if "completeness" in slas:
for col_name, threshold in slas["completeness"].items():
non_null = df.filter(F.col(col_name).isNotNull()).count()
pct = (non_null / total_rows) * 100
results[f"completeness_{col_name}"] = {
"actual": round(pct, 2),
"threshold": threshold,
"passed": pct >= threshold
}
# Uniqueness
if "uniqueness" in slas:
key_cols = slas["uniqueness"]["columns"]
distinct = df.select(key_cols).distinct().count()
is_unique = distinct == total_rows
results["uniqueness"] = {
"distinct": distinct,
"total": total_rows,
"duplicates": total_rows - distinct,
"passed": is_unique
}
# Timeliness
if "timeliness" in slas:
max_age = slas["timeliness"]["max_age_hours"]
timestamp_col = slas["timeliness"]["column"]
latest = df.agg(F.max(timestamp_col)).collect()[0][0]
age_hours = (datetime.now() - latest).total_seconds() / 3600
results["timeliness"] = {
"latest_update": str(latest),
"age_hours": round(age_hours, 1),
"threshold_hours": max_age,
"passed": age_hours <= max_age
}
# Validity
if "validity" in slas:
for rule_name, rule in slas["validity"].items():
valid_count = df.filter(rule["condition"]).count()
pct = (valid_count / total_rows) * 100
results[f"validity_{rule_name}"] = {
"actual": round(pct, 2),
"threshold": rule["threshold"],
"passed": pct >= rule["threshold"]
}
return results
# Eksempel: SLA-sjekk for organisasjons-masterdata
slas = {
"completeness": {
"org_name": 100.0,
"org_number": 100.0,
"address": 95.0,
"contact_email": 80.0
},
"uniqueness": {
"columns": ["org_number"]
},
"timeliness": {
"column": "last_updated",
"max_age_hours": 24
},
"validity": {
"valid_org_number": {
"condition": "LENGTH(org_number) = 9 AND org_number RLIKE '^[0-9]+$'",
"threshold": 100.0
}
}
}
results = check_mdm_quality_slas("lakehouse.default.ref_organizations", slas)
```
### Alerting ved SLA-brudd
```python
# Integrer med Power Automate for varsling
def alert_on_sla_breach(results: dict, webhook_url: str):
"""Send varsel via Power Automate webhook ved SLA-brudd."""
breaches = {k: v for k, v in results.items() if not v.get("passed", True)}
if breaches:
payload = {
"title": "MDM Quality SLA Breach",
"summary": f"{len(breaches)} SLA-brudd oppdaget",
"details": json.dumps(breaches, indent=2, default=str)
}
requests.post(webhook_url, json=payload)
```
---
## Referanser
- [Master data management in Microsoft Purview](https://learn.microsoft.com/en-us/purview/data-governance-master-data-management) -- MDM-oversikt i Purview
- [Detect duplicate records and merge](https://learn.microsoft.com/en-us/power-platform/admin/detect-duplicate-records) -- Duplikatdeteksjon i Dataverse
- [Dataverse as a master data system](https://learn.microsoft.com/en-us/dynamics365/guidance/reference-architectures/dataverse-master-data-system) -- Referansearkitektur for Dataverse MDM
- [Master data management](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/cloud-scale-analytics/govern-master-data) -- MDM i Cloud Adoption Framework
- [CluedIn integration for MDM](https://learn.microsoft.com/en-us/purview/data-governance-master-data-management-cluedin) -- Eventual connectivity for MDM
- [Profisee integration for MDM](https://learn.microsoft.com/en-us/purview/data-governance-master-data-management-profisee) -- MDM med Azure-integrasjon
- [Set up duplicate detection rules](https://learn.microsoft.com/en-us/power-platform/admin/set-up-duplicate-detection-rules-keep-data-clean) -- Konfigurere duplikatregler i Dataverse
---
## For Cosmo
- **Bruk denne referansen** naar kunder trenger a sikre datakvalitet i stamdata for bruk i AI/ML-modeller, eller naar de planlegger MDM-strategi for Microsoft-plattformen.
- **Dataverse er det naturlige valget** for operativ MDM i organisasjoner som allerede bruker Dynamics 365 eller Power Platform. For analytisk MDM, bruk Fabric Lakehouse med SCD Type 2.
- **Entity resolution er kritisk for AI**: Uten riktig deduplisering vil ML-modeller laere fra inkonsistente data. Anbefal hybrid-tilnaerming: deterministic match forst, deretter fuzzy match.
- **For norsk offentlig sektor**: Integrer med nasjonale registre (Folkeregisteret, Enhetsregisteret) som autoritative kilder. Disse bor ha hoyest prioritet i survivorship-regler.
- **SLA-monitorering bor automatiseres**: Sett opp kvalitetssjekker som kjorer daglig og varsler ved brudd, spesielt for data som inngaar i AI-treningspipelines.