Gå til indhold

Design til tredje normalform, og træd så et skridt tilbage

Findes også på 28 sprog

English · Español · 日本語 · Português (Brasil) · Français · Deutsch · Italiano · 한국어 · 简体中文 · Português (Portugal) · 繁體中文 · Bahasa Indonesia · Türkçe · Polski · Tiếng Việt · ไทย · Nederlands · العربية · עברית · Українська · हिन्दी · Русский · Svenska · Norsk bokmål · Suomi · Español (México) · Français (Canada) · Deutsch (Schweiz)

A park seen from above: paths at right angles, and one diagonal shortcut that people kept walking, now deliberately paved, with the old worn track still faint beside it.
Billedet er lavet med AI

Modul 5 af 6 i kapitlet Modellér data for betydning, kapitel 2 i kurset Data Architect. Hvert modul står på egne ben. Forrige: Placér data, hvor de hører hjemme · Næste: Gør modellen til Salesforce

Spørgsmålet, dette modul besvarer: Hvornår skal jeg bevidst bevæge mig væk fra en ren, normaliseret model?

I sidste modul sagde jeg, at du skulle designe til tredje normalform.

Nu vil jeg sige, at du skal bryde den.

Nogle gange.

Det er en vigtig skelnen. Der er stor forskel på ved et uheld at bygge en rodet datamodel og bevidst at denormalisere en ren model. Hvis du ikke forstår, hvor dataene hører hjemme i første omgang, er det ikke arkitektur at kopiere dem et andet sted hen. Det er bare duplikering.

Men når jeg først forstår den rene logiske model, kan jeg træffe en bevidst beslutning om at forme dataene anderledes for de mennesker og systemer, der bruger dem.

Design til tredje normalform, hvor det kan lade sig gøre. Træd så et skridt tilbage, når det er nødvendigt.

Læg mærke til, hvad den sætning ikke siger. Den siger ikke, at tredje normalform er lettere at forstå. Nogle gange er den sværere: en fuldt normaliseret model kan sprede én forretningsidé ud over fem objekter, og de mennesker, der bruger den, må samle den igen i hovedet. Normalisering fortæller mig, hvor hver kendsgerning hører hjemme. Den lover ikke, at det er den letteste form at læse, bruge eller rapportere på. Det er præcis derfor, det at træde tilbage er en designfærdighed og ikke en fiasko.

Start med at modellere sandheden. Beslut så, hvordan den sandhed skal leveres.

Tilbage til hundene, og denne gang træffer vi nogle bevidste valg.

Race: en valgliste eller sin egen tabel? Kør den igennem de spørgsmål, jeg giver dig senere i dette modul. Er der mere end én kolonne med information? Ja: i det mindste størrelsen. Hvor mange værdier? Kennelklubber anerkender et par hundrede racer (American Kennel Club alene oplister 205), langt over min tommelfingerregel på omkring 20. Så Race gør sig fortjent til sin egen tabel, og hver hund peger på sin race. Det afgør det spørgsmål, vi har båret rundt på siden modul 1: Race er en kasse for sig.

Færdighedsniveau: en valgliste. Lærer det, God, Ekspert. Tre etiketter, intet andet at sige om dem, og de ændrer sig ikke. Det er præcis det, en valgliste er til.

Hvor mange tricks kan hver hund? Svaret står allerede i modellen: tæl hundens Hundetrick-poster. Men træneren vil have det tal på hver rapport, for at sortere og filtrere på det uden at bygge en rapport på tværs af to tabeller. Så jeg træder et skridt tilbage og holder et Kendte tricks-antal direkte på hunden. Det er en kopi. Sandheden bor stadig i Hundetrick; antallet er en gengivelse af den, og det skal holde trit. Salesforce giver os en ren måde at gøre præcis det på, og det ser vi i modul 6.

Nu kommer drejningen: hundeskolen begynder at tage imod katte. Hvad gør vi? Én mulighed: tilføj en Kat-tabel ved siden af Hund-tabellen og et Kattetrick ved siden af Hundetrick. Alting fordobles: to af hver skærm, to af hver rapport, og den dag de tager kaniner ind, tre. Den anden mulighed: træd et skridt tilbage, og læg mærke til, at en kat har en ejer, måske en opdrætter, en race, en fødselsdato og, med tålmodighed, et trick eller to. De samme kendsgerninger og de samme relationer som en hund. Så vi generaliserer: et Kæledyr med en Art, hund eller kat. Hver race hører også til en art, og det er der, arten i virkeligheden bor: en labrador er en hund. Kæledyret bærer en kopi, med vilje, så hver skærm og rapport kan starte med »hund eller kat?« uden at slå racen op. Endnu en bevidst kopi, og i modul 6 får den sit eget job.

Det er at designe til forandring, og det er en afvejning. Generalisér for tidligt, og alting bliver en vag »Ting« med et typefelt, som ingen forstår. Jeg generaliserer, når forretningen faktisk kommer med den anden slags, og de to har næsten alt til fælles, sådan som hunde og katte har her. Hvis katte havde brug for meget forskellige kendsgerninger, ville jeg tænke mig om to gange.

Kæledyrsmodellen efter afvejningerne Kæledyrsmodellen som en detaljeret datamodel. Kæledyr sidder, hvor Hund sad: kæledyrs-id, også kendt under sit mikrochipnummer, id'erne for ejer, opdrætter og race, Art (en valgliste: hund eller kat), navn, fødselsdato og et antal Kendte tricks, der bevares til rapportering. Race er nu forbundet (et kæledyr er én race) og har sin egen art, navn og størrelse. Kæledyrstrick, mellem Kæledyr og Trick, har færdighedsniveauet som valgliste og indlæringsdatoen; Trickvurdering, under det, har dato, færdighedsniveau og hvem der vurderede. En ejer ejer kæledyr, og en opdrætter opdrætter dem, som før. ejer opdrætter er en kan kendes i tjekkes i Ejer Ejer-id POST-ID Navn Telefon ZIP By Opdrætter Opdrætter-id POST-ID Navn By Kæledyr Kæledyrs-id POST-ID Mikrochipnummer OGSÅ KENDT SOM Ejer-id Opdrætter-id Race-id Art (valgliste) Navn Fødselsdato Kendte tricks (antal) Race Race-id POST-ID Art (valgliste) Navn Størrelse Kæledyrstrick Kæledyrstrick-id POST-ID Kæledyrs-id Trick-id Færdighedsniveau (valgliste) Indlæringsdato Trick Trick-id POST-ID Navn Sværhedsgrad Trickvurdering Trickvurderings-id POST-ID Kæledyrstrick-id Dato Færdighedsniveau (valgliste) Vurderet af præcis én nul eller én én eller mange nul eller mange © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Nu de samme slags valg hos Steve Trucking, hvor der er mere på spil.

Den reneste model er ikke altid det bedste system

Sektion kaldt “Den reneste model er ikke altid det bedste system ”

Forestil dig et team ved et stop. Leveringen har sine varer. Installationen har en tjekliste. Hvert trin kræver billeder. Modtageren skriver under.

Den normaliserede model er smuk: Levering → Leveringslinje → Installationstjekliste → Billede, hver der, hvor den hører hjemme.

Så sætter jeg mig ned med de mennesker, der faktisk bruger den. Et team lukker cirka ti stop om dagen, i indkørsler, ofte uden dækning. Hvis min smukke model sender dem gennem en labyrint af skærme og relaterede lister for at afslutte ét stop, har jeg et arkitekturproblem.

Datamodellen er ikke det eneste, vi designer.

Vi designer et system.

Det er en af grundene til, at jeg nogle gange træder væk fra en perfekt normaliseret model: brugeroplevelsen.

Måske kunne et begreb teknisk set være sin egen entitet, men at skille det ud tilføjer kompleksitet, der giver meget lidt værdi. Måske er en forælder med flere niveauer af børn akademisk ren, men elendig at indtaste og vedligeholde. Måske er begrebet lille, stabilt og mest brugt som et valg.

Det er her, jeg holder op med kun at spørge: »Hvor hører denne kendsgerning teoretisk hjemme?« og begynder at spørge: »Hvordan skal dette system faktisk bruges?«

Det betyder ikke, at hver klage over et ekstra klik gør modellen fladere. Det betyder, at brugervenlighed er et legitimt arkitektonisk input.

Rapportering er en anden almindelig grund.

Hver detailpartner vil have et scorecard: rettidige leveringer pr. region, pr. måned. I den rene model kender en levering sit distributionscenter, og DC’et kender sin region. Teknisk set kan vi navigere det.

Men kan rapportværktøjet? Kan de mennesker, der bygger deres egne rapporter? Kan de besvare spørgsmålet uden en rapporteringsarkitektur, der er mere kompliceret end selve spørgsmålet?

Det er der, jeg måske kopierer eller udleder regionen over på leveringen, tættere på det sted, hvor den bliver brugt.

Nu har jeg indført duplikering. Så jeg har brug for et spørgsmål mere: hvem ejer sandheden?

Hvis kildeværdien ændrer sig, hvad sker der så med min kopi? Skal den ændre sig? Eller skal den beholde det, der var sandt, da leveringen fandt sted? Det er forskellige krav.

Denormalisering fjerner ikke kompleksitet.

Den flytter den.

Her er et mindre eksempel, som Salesforce-admins møder hele tiden. Brugeren skal vælge fra et sæt værdier. Opretter jeg endnu en entitet og relaterer til den, eller bruger jeg en valgliste?

Tag en leverings status: planlagt, læsset, ude til levering, på vej, leveret, installeret, undtagelse, returneret. En kort, stabil liste af etiketter. En valgliste er præcis det, jeg vil have.

Tag nu typen af stop: kun levering, levering med installation, levering med bortkørsel. Den bærer sin egen information: hvor lang tid stoppet tager, hvilke færdigheder teamet skal have, hvilken installationstjekliste der gælder. Den ændrer sig uafhængigt, og forretningen administrerer den. Det er en entitet, ikke en etiket.

Hvis jeg opretter et objekt for hvert begreb, der teoretisk kunne normaliseres, kan jeg bygge et teknisk smukt system, som ingen nyder at bruge. Hvis jeg gør hvert begreb til en valgliste, fordi det er nemt, kan jeg meget hurtigt male mig selv op i et hjørne.

Så jeg spørger: har det sin egen information? Relationer? Ændrer det sig uafhængigt? Skal det administreres som data? Kan forretningen på et tidspunkt få brug for mere fra det end en etiket?

Her er de spørgsmål, jeg faktisk stiller i en designsession.

Er der mere end én kolonne med information? Hvis værdien har brug for en beskrivelse, en varighed, en liste over færdigheder, en ejer, er det ikke længere en etiket.

Hvor mange værdier? Min tommelfingerregel er omkring 20. Over 20 værdier begynder en valgliste at bryde sammen, og så er det tid til at tænke på et objekt. Stater, med deres halvtreds, er den undtagelse, vi lever med, og lande er værre; helt ærligt, er der nogen, der elsker valglister med lande? Jeg synes, de er irriterende.

Bliver værdierne oprettet over tid, og af hvem? At tilføje en værdi til en valgliste er en konfigurationsændring, og det betyder en admin. Hvis forretningen tilføjer værdier hver uge, og de, der tilføjer dem, ikke er admins, lægger en valgliste en ticket foran hver ny værdi.

Skal folk filtrere og rapportere på det? Valglister er gode til det. Lookups er ikke lige så rene. Hver lookup tilføjer et hop: en rapporttype følger kun en kort kæde af relaterede objekter (en brugerdefineret rapporttype tillader højst fire objektrelationer), skærmen bliver til relaterede lister inde i relaterede lister, og koden bliver mere kompliceret.

En værdiliste starter ofte sit liv som en valgliste og gør sig med tiden fortjent til sit eget objekt. Lad den gøre sig fortjent til det.

En etiket eller en entitet? Status og typen af stop To kort. Leveringsstatus, en valgliste: otte stabile værdier, hver et enkelt ord eller et ord med bindestreg (Planlagt, Læsset, Ude-til-levering, Ankommer, Leveret, Monteret, Afvigelse, Returneret), og hver er bare en etiket. Type stop, en entitet: fireogtyve værdier og flere kommer, for eksempel kun levering, levering plus montering af en vaskemaskine eller et gaskomfur, levering plus bortkørsel, kun bortkørsel, returafhentning og atten mere; hver har sin egen stopvarighed, nødvendige teamfærdigheder og tjekliste til montering. En note nedenunder: over omkring 20 værdier, eller med egne attributter, er det en entitet, ikke en etiket. Leveringsstatus en valgliste VÆRDIERNE: 8, OG STABILE Planlagt Læsset Ude-til-levering Ankommer Leveret Monteret Afvigelse Returneret HVER VÆRDI ER Bare en etiket Type stop en entitet VÆRDIERNE: 24, OG FLERE KOMMER Kun levering Levering + montering: vaskemaskine Levering + montering: gaskomfur Levering + bortkørsel Kun bortkørsel Returafhentning …og 18 mere HVER VÆRDI HAR SIN EGEN Stopvarighed Nødvendige teamfærdigheder Tjekliste til montering Over omkring 20 værdier, eller egne attributter: så er det en entitet, ikke en etiket. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Et design, der fungerer smukt med et par tusinde poster, kan opføre sig helt anderledes med millioner.

Så kig ikke kun på diagrammet. Kend tallene.

Steve Trucking laver cirka en million leveringer om året, med en vækst på 30 % om året. Hver levering samler cirka otte statusopdateringer. Det er otte millioner statusposter i år og cirka 13,5 millioner om året i år tre. Læg dertil fire-fem millioner billeder om året.

Samme model. Meget forskellig arkitektur.

Vi går meget dybere i Arkitektur i stor skala. Indtil videre skal du huske: volumen kan ændre en beslutning om datamodellering. En relation, der er logisk korrekt, er ikke automatisk det bedste fysiske design i enhver skala.

Forskellige forbrugere vil have forskellige former

Sektion kaldt “Forskellige forbrugere vil have forskellige former ”

Indtil nu har vi tænkt på det operationelle system. Koordinatorer planlægger ruter for leveringer. Teams lukker stop. Systemet ændrer sig, mens forretningen kører.

Men forretningen vil også analysere mange års historik. Hvilke partnere og regioner er forsinkede? Hvordan har leveringstiden ændret sig? Hvor ofte kræver en installation et ekstra besøg?

Et analytisk system vil måske have den samme information organiseret anderledes. Du vil høre ord som datavarehus, fakta, dimension og stjerneskema. Dem pakker vi ikke ud her; hos Steve Trucking er det Snowflake-datavarehuset, og vi vender tilbage til det senere i kurset.

Indtil videre: forskellige forbrugere kan have brug for forskellige former af den samme sandhed.

Og nu er der endnu en forbruger: AI.

En modtager skriver en sms: »Hvor er min levering?« En AI-assistent kunne slå det her op:

Levering 10427, rute 3312, stop 7, lastbil 117, tidsvindue 13.00–15.00.

En traditionel applikation er helt tilfreds med at følge de relationer. Men for at svare modtageren har assistenten brug for kontekst, der er samlet fra flere steder:

Din Redrock-opvaskemaskine er det syvende stop på dagens rute fra distributionscentret i Phoenix. Lastbilen er tre stop væk, og du er stadig inden for dit tidsvindue kl. 13–15.

Vi har taget information fra flere relaterede entiteter og samlet en fladere, kontekstrig gengivelse til én bestemt forbruger.

Det betyder ikke, at jeg ødelægger min normaliserede model. Og det betyder bestemt ikke »AI kan lide flade data, så læg alt i ét kæmpe objekt«. Gør ikke det.

Sandhedskilden forbliver ren. AI får en gengivelse, der er bygget til det job, den udfører. Det er den samme idé, som vi lige så med analyse:

Én sandhedskilde kan understøtte flere former til forbrug.

Vi går meget dybere ind i grounding og hentning senere i kurset.

Der er en fare her.

Hvis jeg kopierer regionen over på leveringen til rapportering, sender en fladgjort udgave til Snowflake og bygger en kontekstrig udgave til AI-assistenten, hvilken af dem er så korrekt?

Det spørgsmål skal have et svar. Jeg vil vide, hvor den autoritative værdi bor. Alt andet er en gengivelse af den sandhed til et formål.

Det sted er system of record (kildesystemet). Denormaliserede kopier kan være gode: stopskærmen, scorecardet, Snowflake og AI-konteksten gør hver især deres job bedre med en form, der er bygget til dem, og det er fint at slå op i dem. Men når noget ændrer sig, starter ændringen i kildesystemet, typisk relationsmodellen, og flyder udad til hver kopi. Ingen retter regionen i Snowflake eller redigerer AI’ens kontekst i hånden. Ret det ved kilden, og lad ændringen flyde.

Kildesystemet: ændringer flyder udad Én kasse øverst, kildesystemet (system of record), relationelt, hvor ændringer starter, med pile, der flyder ned til fire kopier bygget ud fra det: teamets stopskærm, med ét stop, alt på én side; partnerens scorecard, forsinkede leveringer pr. region; Snowflake-datavarehuset, mange års historik; og AI-konteksten for leveringer, til »Hvor er min levering?«. En note nedenunder: ændringer starter i kildesystemet og flyder ud til hver kopi; ret aldrig en kopi. System of record relationel: ændringer starter her Teamets stopskærm ét stop, alt på én side Partnerens scorecard forsinkede leveringer pr. region Snowflake-datavarehus mange års historik AI-kontekst for leveringer »Hvor er min levering?« Ændringer starter i kildesystemet og flyder ud til hver kopi. Ret aldrig en kopi. © 2026 Twinshark LLC · stevetecharc.com
Click to enlarge

Og det betyder mest, når data ændrer sig. Hvis et distributionscenter flytter til en anden region i dag, skal sidste måneds leveringer så vise den nye region? Måske. Måske ikke. Til historikken har jeg måske brug for den region, der var sand, da leveringen fandt sted. Det er ikke længere et synkroniseringsproblem. Det er en forretningsbeslutning.

Det er derfor, denormalisering aldrig bør ske ved et uheld. Hver kopieret kendsgerning rejser spørgsmål om ejerskab, synkronisering, historik og tillid. Det er afvejningstankegangen fra kapitel 1: vid, hvad du køber (en lettere skærm, en enklere rapport, bedre kontekst til AI), og hvad du betaler (kopierede data, synkronisering, et mere kompliceret ejerskab af sandheden). Og fordi vi startede fra en ren logisk model, kan vi pege på hver kopi og sige: »Jeg ved, at det her hører hjemme derovre. Jeg placerer en gengivelse af det her på grund af dette krav.« Det er en beslutning, vi kan gennemgå, udfordre og skrive ned, så den næste arkitekt ved hvorfor.

Når jeg overvejer denormalisering, beslutter jeg:

  • Hvor den autoritative kilde til hver forretningskendsgerning bor.
  • Om den rene model skaber reelle problemer for brugere, rapportering, skala eller ydeevne.
  • Om en enklere gengivelse er duplikeringen værd, og hvordan kopien forbliver troværdig.
  • Om historiske værdier skal ændre sig, når den aktuelle kilde ændrer sig.
  • Om analyse eller AI har brug for en anden form af dataene end det operationelle system.

Udgangspunktet ændrer sig aldrig: vid, hvor sandheden hører hjemme. Når kravene så retfærdiggør det, så form den til levering.

Nu kommer Salesforce tilbage i billedet. Vi skal gøre det, vi har designet, til en fysisk datamodel.