Kapittel 5 · Forelesning 10 · Lærebok 8, 10, 11, 29

Utover relasjonsmodellen

Når 1NF blir en tvangstrøye. Komplekse typer, JSON, MapReduce, NoSQL, CAP og datalager — og når de gir mening framfor (eller sammen med) en klassisk RDBMS.

01 · Hvorfor bryte ut

Når relasjonsmodellen blir en tvangstrøye

Den relasjonelle modellen er strålende for det den er bygd for: strukturerte data med klare skjemaer, sterke integritetskrav og spørringer på tvers av relasjoner. Men over de siste tjue årene har tre press-punkter blitt umulige å overse — og de drev fram både SQL-utvidelser og helt nye familier av databasesystemer.

Skala
Webskala-applikasjoner: tusenvis av maskiner, petabyte med data. En enkelt RDBMS-instans skalerer ikke vertikalt nok.
Form
Logger, dokumenter, JSON fra API-er, sosiale grafer, geometri, tekstdokumenter — passer dårlig som flate, normaliserte tabeller.
Fart
Strømmer av hendelser i sann tid. ACID-låsing per transaksjon koster mer enn applikasjonen tjener på det.

Svaret kom i to spor: utvid SQL (objekt-relasjonelle typer, JSON, arrays — alt fortsatt i én transaksjonell motor) og bygg nye systemer (NoSQL, distribuerte filsystemer, MapReduce). Et godt tommelfingerregel: relasjoner først, andre verktøy bare når relasjonsdata-modellen faktisk sliter.

Sentralt poeng

"NoSQL" betydde opprinnelig "Not SQL", men brukes i dag oftere om "Not Only SQL". De fleste produksjonsstacker er hybride: en RDBMS for kjernen, og spesialdatabaser for spesifikke arbeidsmengder.

02 · Komplekse datatyper

Klasser, arv og pekere — i SQL

Ren relasjonsmodell krever 1NF: hver attributtverdi er atomær. Det er en tvangstrøye for naturlig strukturerte data — adresser, koordinater, lister av interesser. Standard-SQL siden 1999 lar deg definere strukturerte typer, arve dem, og bruke arrays og pekere — uten å forlate relasjonsmotoren.

Strukturerte typer (UDT)

CREATE TYPE Address AS (
  street    VARCHAR(60),
  city      VARCHAR(40),
  zip       CHAR(4)
);

CREATE TYPE Person AS (
  name      VARCHAR(40),
  address   Address,                  -- nested struct
  phones    VARCHAR(20) ARRAY[3]    -- array av primitiver
);

En strukturert type grupperer flere felt under ett attributt-navn. Du leser dem med dot-notasjon: p.address.city. Arrays og multisets gjør 1NF til en valgfri restriksjon, ikke en lov.

Type-arv

Person name, address Student + totCredits + degree Teacher + salary + dept
Subtyper arver alle felt fra supertypen og kan legge til egne. En Student er også en Person.
CREATE TYPE Student UNDER Person (
  totCredits  INTEGER,
  degree      VARCHAR(20)
);

SQL skiller mellom type-arv (typene arver felt og metoder) og tabell-arv (subtabeller arver rader fra supertabellen). I PostgreSQL er det syntaks: CREATE TABLE student () INHERITS (person);. Da ligger hver studentrad også i person-spørringer — om du ikke skriver SELECT * FROM ONLY person.

Pekere (referansetyper)

I stedet for å lagre fremmednøkkel-attributter og selv stå for join-en, lar referansetyper deg si "dette feltet peker på en rad i tabellen people":

CREATE TABLE articles (
  title  VARCHAR(120),
  author REF(Person) SCOPE people
);

-- Path-uttrykk: følger pekeren uten eksplisitt JOIN
SELECT a.title, a.author->name
FROM articles AS a;
Vær obs

Strukturerte typer, arv og REF brukes relativt sjelden i moderne PostgreSQL/MySQL — de fleste velger heller JSONB-kolonner eller en rein normalisert relasjon. Men eksamen kan spørre om syntaks og semantikk.

Spørsmål · Lett
Hva er forskjellen mellom type-arv og tabell-arv i objekt-relasjonell SQL?
Riktig. Type-arv er kompileringstidens arv (struktur-nivå). Tabell-arv legger til data-nivå-arv: SELECT * FROM person finner også studenter, om du ikke skriver FROM ONLY person.
Spørsmål · Middels
Du har articles.author REF(Person) SCOPE people. Hva gjør a.author->name i et SELECT?
Akkurat. Path-uttrykket x->y dereferanser pekeren og henter feltet y fra mål-raden. Det er sukker over en JOIN.
03 · Semi-strukturert: JSON og XML

Skjema som kan, men ikke må

Semi-strukturert data har noe struktur (taggene/nøklene er der), men forskjellige poster trenger ikke ha samme felt. To formater dominerer: JSON for moderne webtjenester, XML for eldre B2B-utveksling og dokumenter.

{} student "id": 12345 "name": "Alvalds" "emner": [ ] {} "kode":"TDT4145" "poeng":7.5 {} "kode":"TDT4173" "poeng":7.5 {} "kode":"TFY4108" "poeng":7.5
JSON er et tre. Indre noder er objekter ({ }) eller arrays ([ ]); løv er primitiver (tall, strenger, booleaner, null).

JSON i moderne SQL

PostgreSQL har JSON (rå tekst) og JSONB (binær, indekserbar). MySQL har en analog JSON-type. Å lagre JSON i en kolonne er ikke "juks" — det gir deg fleksibelt skjema for de feltene som varierer, mens fremmednøkler og indekser fortsatt fungerer på de som er stabile.

PostgreSQL — JSONB-spørring
SELECT
  data->>'name'      AS name,
  data->'emner'->0
       ->>'kode'      AS firstcourse,
  jsonb_array_length(
       data->'emner')    AS n_courses
FROM students
WHERE data @> '{"campus":"NTNU"}';
Operatorer å huske
->Hent felt som JSON
->>Hent felt som tekst
#> / #>>Path som array
@>Inneholder (containment)
?Har nøkkel

SQL/JSON-standarden gir også JSON_VALUE, JSON_QUERY og JSON_TABLE (det siste flater ut JSON til vanlige rader). Du kan opprette en GIN-indeks på en JSONB-kolonne for raske containment-spørringer.

XML — eldre, men ikke borte

XML er fortsatt vanlig i bank, helse og myndighet. Spørrespråket er XPath/XQuery:

/* XPath-uttrykk i XQuery */
for $b in doc("books.xml")//book
where $b/price < 100
return $b/title
Når JSON i SQL gir mening

Konfig-pakker, audit-payloads, ymse "metadata"-bag-attributter, fleksible produktattributter (skjema varierer per kategori). Når alle felt er stabile og brukes mye i WHERE/JOIN — normaliser dem heller.

Spørsmål · Middels
Hva returnerer data->'emner' versus data->>'emner' i PostgreSQL?
Korrekt. Bruk -> når du fortsetter å navigere i JSON-strukturen, ->> bare når du tar ut en endelig tekst-/skalarverdi.
Spørsmål · Vanskelig
Du designer et produkt-skjema. Hvilken av disse er best praksis?
Hybrid-tilnærmingen er standardrådet: relasjon for det stabile, JSON for det varierende. Du beholder integritet og indeks-effektivitet der det teller.
04 · Object-relasjonelt og ORM

Klasser i koden, tabeller på disk

Selv med UDT i SQL ligger applikasjonens klasser i et programmeringsspråk og dataene i en relasjonsdatabase — to verdener. ORM-rammeverk (Hibernate, Django ORM, SQLAlchemy, JPA) kobler dem: hver klasse mappes til en tabell, hver instans til en rad, og navigasjon mellom objekter (person.address.city) blir til implisitte joins.

ORM gir deg

  • Skjema-migreringer som kode
  • Portabilitet på tvers av RDBMS
  • Mindre boilerplate for CRUD
  • Naturlig domenemodell i applikasjonskoden

ORM koster

  • "N+1-problemet" når lazy loading skjuler joins
  • Bulk-oppdateringer er klønete
  • Komplekse spørringer ender ofte som rå-SQL likevel
  • Skjuler det som faktisk koster (indekser, planer)

Object-relasjonelle SQL-features og ORM-rammeverk løser samme grunnleggende friksjon — bare på hver sin side. Begge er nyttige, men sjelden noe svar i seg selv på "skal jeg bruke noe annet enn relasjonsmodellen?".

05 · Big Data og 3 V-er

Når data sprenger én maskin

"Big data" er et utflytende begrep. Den klassiske definisjonen er Doug Laneys 3 V-er:

Volume
Tusenvis av maskiner, petabyte. Tradisjonelle parallelle DB-er traff hundretalls noder, ikke titusenvis.
Velocity
Strømmer av events i sann tid — sensorer, klikk, transaksjoner — ikke batch-loader hver natt.
Variety
Relasjon, JSON, fri tekst, bilder, geometri, grafer. Ett verktøy duger ikke.

Distribuerte filsystemer — HDFS

Når én disk er for liten, deler vi data over mange maskiner. HDFS (Hadoop Distributed File System), inspirert av Googles GFS, er det kanoniske eksempelet:

  • NameNode — én master holder metadata: hvilke filer finnes, hvilke blokker hører til, hvor ligger blokkene.
  • DataNodes — mange maskiner som lagrer faktiske blokker (typisk 64–128 MB hver).
  • Replikering — hver blokk lagres i flere kopier (default 3) på forskjellige noder, så feil på én maskin ikke mister data.
  • Optimalisert for store filer (titalls MB til hundrevis av GB), append-mønster, og scan-tunge spørringer — ikke for mange små filer eller in-place updates.
Kontrast til RDBMS

HDFS er bare et filsystem. Det vet ingenting om skjema, rader eller transaksjoner. Det er bærebjelken man bygger Hive, Spark, HBase og MapReduce-jobber oppå.

06 · MapReduce

Programmeringsmodellen som starter alt

MapReduce er et programmeringsmønster der du skriver to rene funksjoner, og rammeverket tar seg av all koordineringen — parallellisering, sortering, feiltoleranse, gjenstart av krasjede maskiner.

Definisjon
map & reduce

map(record) → emit(key, value) kjøres på hver inn-record uavhengig, parallelt, der dataene ligger.
reduce(key, list<value>) → output kjøres på alle verdiene som delte samme key etter en automatisk shuffle.

Input-blokker Map Shuffle Reduce "han ler ler" "vi ler" "de ser han" (han,1)(ler,1) (ler,1) (vi,1)(ler,1) (de,1)(ser,1) (han,1) han: [1,1] ler: [1,1,1] vi: [1] de: [1] · ser: [1] (han, 2) (ler, 3) (vi, 1) (de, 1) · (ser, 1)
Klassisk word-count: hver mapper teller ord lokalt, shuffle samler like nøkler, reducer summerer.

Alle relasjonelle operasjoner kan uttrykkes med map+reduce — men i praksis bruker man heller Apache Spark (DAG av operatorer, lazy evaluation, in-memory caching) eller SQL-laget Hive/Pig som kompilerer til MapReduce eller Spark.

Spørsmål · Middels
Hva er shuffle-fasen i MapReduce?
Helt riktig. Shuffle er hjertet av MapReduce — det er der nettverkstrafikken faktisk skjer, og det rammeverket håndterer for deg.
07 · NoSQL — fire familier

Fire typer dataforhold, fire datamodeller

NoSQL-bevegelsen er ikke ett system, men en familie av spesialiserte datamodeller. Hver er optimalisert for et bestemt aksess-mønster og ofrer noe (oftest sterk konsistens og rik spørring) for å vinne noe annet (skala, lav latens, fleksibelt skjema).

K
Key-value
put / get / delete
Redis · DynamoDB · Memcached

Cache, sesjons-data, leaderboards. Ekstremt rask når du vet nøkkelen. Ingen joins eller spørring på verdier.

D
Dokument
JSON-trær
MongoDB · Couchbase

CMS, produktkataloger, brukerprofiler. Dokumenter med varierende felt; rik filtrering og indeksering inne i JSON.

C
Kolonne-orientert
Wide-column
Cassandra · HBase · Bigtable

Tidsserier, IoT, analytics-tabeller med milliarder rader. Sparse skjema, rask write, range-skann på radnøkkel.

G
Graf
Noder + kanter
Neo4j · ArangoDB · JanusGraph

Sosiale nettverk, anbefalinger, fraud-deteksjon. Spørringer langs stier blir billige der rekursive joins er smertefulle.

Eksempel: samme data, fire modeller

Si vi vil lagre at Alvalds (id 12345) tar emnet TDT4145:

Dokument (MongoDB)
db.students.insertOne({
  _id: 12345,
  name: "Alvalds",
  emner: [
    { kode: "TDT4145", sem: "V26" },
    { kode: "TDT4173", sem: "V26" }
  ]
})

db.students.find({
  "emner.kode": "TDT4145"
})
Graf (Cypher / Neo4j)
CREATE (s:Student {id:12345, name:"Alvalds"}),
       (c:Course  {kode:"TDT4145"}),
       (s)-[:TAR {sem:"V26"}]->(c);

// Hvem tar TDT4145?
MATCH (s:Student)-[:TAR]->(:Course {kode:"TDT4145"})
RETURN s.name;
Spørsmål · Middels
Du bygger en social-graph-funksjon: "venner-av-venner som liker pizza". Hvilken NoSQL-familie er tydeligst riktig?
Stemmer. I SQL ville det vært en kjede selvjoins eller rekursiv CTE; i en grafdatabase er det en enkel MATCH-pattern langs to :VENN-kanter.
Spørsmål · Vanskelig
Cassandra og MongoDB beskrives ofte begge som "NoSQL". Hva er den viktigste arkitekturelle forskjellen mellom dem?
Helt rett. Begge er distribuerte og horisontalt skalerbare, men spørremønstrene de er bygget for skiller seg betydelig — Cassandra er sterkest når du leser hele rad-områder etter en partisjons-nøkkel, MongoDB når du filtrerer inne i dokumenter.
08 · Sharding og replikering

Hvordan distribuerte systemer faktisk skalerer

To uavhengige akser holder distribuerte data-systemer i live: sharding (skala) og replikering (tilgjengelighet og ytelse).

Sharding — horisontal partisjonering

Vi splitter radene i en logisk tabell på tvers av flere noder. En shard key bestemmer hvor en gitt rad havner.

Range-partisjonering

Node 1: id 0–999, Node 2: id 1000–1999 …

  • Range-spørringer (WHERE id BETWEEN …) treffer få noder.
  • Skjev nøkkelfordeling lager hot shards.

Hash-partisjonering

Node = hash(id) mod N.

  • Jevn lastfordeling.
  • Range-spørringer må treffe alle noder.
  • Re-sharding er smertefullt → bruk consistent hashing.
Tabell orders · partisjons-nøkkel = customer_id Node A — hash 0–N/3 customer 14 customer 33 customer 47 replikaer på B, C Node B — hash N/3–2N/3 customer 02 customer 19 customer 91 replikaer på A, C Node C — hash 2N/3–N customer 08 customer 55 customer 76 replikaer på A, B
Hver rad har én primær-shard (etter hash av nøkkel) og kopier på minst to andre noder. Mister vi A, kan B eller C ta over hennes radoppslag.

Replikering

Hver shard kopieres til flere noder — typisk 3 — for at databasen skal overleve maskin- eller diskfeil.

  • Leader / follower: én primær aksepterer skriv; følgere er read-only kopier.
  • Multi-leader: flere noder aksepterer skriv → må håndtere konflikt-merging.
  • Quorum: skriv lykkes når W av N bekrefter; les lykkes med R av N. Hvis R + W > N, ser leseren alltid den siste skrivingen.
09 · CAP & BASE

Hvorfor du velge — interaktivt

Eric Brewers CAP-teorem: et distribuert system kan garantere maksimalt to av tre egenskaper når en nettverkspartisjon oppstår.

Definisjoner
  • C — Consistency: alle noder ser samme data samtidig. Etter en skriv leser alle den nye verdien.
  • A — Availability: hver request får et svar (riktig eller stale, men ikke en feil).
  • P — Partition tolerance: systemet fortsetter å fungere selv om nettverket deler seg i isolerte øyer.

Siden nettverkspartisjoner faktisk skjer i praksis, er P obligatorisk i ekte distribuerte systemer. Det reelle valget er C eller A — under partisjon:

C Consistency A Availability P Partition-tol.
Klikk to hjørner
Velg en kombinasjon
CAP sier at i nærvær av nettverkspartisjon må du gi opp én. Klikk to hjørner for å se hva systemer som velger den kombinasjonen ser ut som — og hvilke kjente databaser som hører hjemme der.

BASE — alternativet til ACID

NoSQL-systemer som velger AP (tilgjengelighet over konsistens) trenger en svakere kontrakt enn ACID. Den heter BASE:

Basically Available Systemet svarer alltid — men kanskje med "stale" data.
Soft state Tilstanden kan endres uten input, drevet av replikasjons-protokollen.
Eventually consistent Når skrivinger slutter, vil alle replikaer til slutt konvergere til samme verdi.
Vanlig misforståelse

"Eventuell konsistens" betyr ikke "ingen konsistens". Det betyr at vinduet hvor en leser kan se utdaterte data er begrenset, ikke null. For en sosial feed er det helt greit; for et bankoppgjør er det ikke det.

Spørsmål · Lett
Hva betyr "P" i CAP-teoremet?
Riktig. Og siden partisjoner faktisk skjer (kabel kuttes, switch dør), er P i praksis ikke valgfri — så valget står mellom C og A under partisjon.
Spørsmål · Vanskelig
Et betalingssystem velger CP framfor AP. Hva skjer ved en nettverkspartisjon?
Korrekt. CP-systemer (HBase, ZooKeeper, klassiske RDBMS-replikkluster) avviser heller skrivinger enn å risikere divergerende data — riktig for penger, ID-er, lager.
10 · OLAP og datalager

To verdener: online og analytisk

Den samme bedriftens database brukes til to vidt forskjellige typer arbeid. OLTP (online transaction processing) og OLAP (online analytical processing) har så ulike krav at det vanligvis lønner seg å skille dem fysisk.

OLTPOLAP
SpørringerMange, korte, nøkkel-baserteFå, lange, store skann + aggregeringer
SkrivHyppig, kritiskPeriodisk batch-load
SkjemaNormalisert (3NF/BCNF)Denormalisert (star/snowflake)
LagringRad-orientertKolonne-orientert (komprimerer bedre)
EksemplerPostgreSQL, MySQL, Oracle OLTPSnowflake, BigQuery, Redshift, Vertica

Star-schema

Sentralt i et datalager står fakta-tabellen: en bred tabell med målbare hendelser (salg, klikk, transaksjon) og fremmednøkler til dimensjons-tabeller som beskriver konteksten.

sales (fakta) date_id, store_id, item_id, cust_id qty, price date day · month · qtr · year store store_id · city · region item item_id · category · color customer cust_id · age · segment promotion promo_id · type · discount
Star-schema: én fakta-tabell i midten, dimensjons-tabeller rundt. Snowflake-schema er bare en variant der dimensjonene selv er normaliserte.

OLAP-operasjoner

  • Slice / dice — fikser én eller flere dimensjoner (f.eks. "vis bare salg i 2025 og kategori = elektronikk").
  • Drill-down / roll-up — finere/grovere granularitet (måned → uke → dag, eller motsatt).
  • Pivot — bytt akser i pivot-tabellen.
  • Data cube — pre-aggregerte sum-tabeller på alle subset av dimensjoner. SQL: GROUP BY CUBE(date, store, item).

ETL og datalagre

Data flyter fra OLTP-systemer til datalageret via ETL (Extract → Transform → Load): rensing, deduplisering, formatkonvertering. Moderne varianter snur til ELT (load først, transformer i lageret) for å utnytte parallelle motorer.

Data lake er et alternativ: rå data i alle formater i et billig filsystem (typisk S3 / HDFS), uten skjema-pålegging på inntak. Skjema-on-read gir fleksibilitet, men flytter kompleksiteten til hver spørring.

Spørsmål · Middels
Hva er den primære grunnen til at OLAP-systemer ofte bruker kolonne-orientert lagring?
Riktig. SELECT SUM(qty) FROM sales WHERE year=2025 trenger to kolonner av kanskje tjue. Rad-orientert layout tvinger oss til å lese alle. Kolonne-orientert + run-length encoding gir 10×–100× speedup.
Spørsmål · Vanskelig
Forskjellen mellom et data warehouse og en data lake i én setning?
Helt rett. "Schema-on-write" vs "schema-on-read" er den klareste skillelinjen. I praksis sees ofte hybrider — "lakehouse" (Delta Lake, Iceberg) prøver å gi varehus-spørringsytelse på lake-lagring.
11 · Når brukes hva?

Et beslutnings-cheatsheet

Det vanlige svaret er kjedelig, men sant: start med en relasjonsdatabase. Bytt eller utvid kun når et konkret krav tydelig ikke passer modellen.

BehovVelgHvorfor
Strukturert kjernedata, transaksjoner, integritet RDBMS (Postgres, MySQL) ACID, joins, modne verktøy. Fortsatt det riktige standardvalget.
Fleksibelt skjema med noen variable felt RDBMS + JSONB Det beste fra begge — relasjon for det stabile, JSON for det varierende.
Cache, sesjoner, leaderboards Key-value (Redis) Ekstremt rask get / put, ingen behov for joins.
Dokumenter med varierende felt, høyt volum Dokument-DB (MongoDB) JSON-spørring, indekser inne i dokumenter, horisontal skala.
Tidsserier, IoT-events, milliarder rader Wide-column (Cassandra) / tidsserie-DB Skriv-tungt, range-skann etter (entity, time), partisjons-vennlig.
Stier, sosiale grafer, anbefaling Grafdatabase (Neo4j) Sti-spørringer på flere hopp blir billige.
Analytics, dashboards, BI Datalager (Snowflake, BigQuery) Kolonne-lagring, MPP-spørringsmotor, optimalisert for store skann.
Råe events for senere analyse Data lake (S3 + Spark) Ingen forhåndsforpliktelse til skjema, billig lagring.
Når ikke droppe relasjonsmodellen
  • Du tror du trenger skala — men er ikke i nærheten av terabyte-grensen ennå.
  • "Skjema-fritt" høres frigjørende ut — helt til hvert Java-deserialisering må håndtere fem ulike historiske formater.
  • Joins er upraktiske — eller bare manuelle, fordi NoSQL-en ikke har dem.
  • "Vi blir konsistent etter hvert" passer ikke for penger, lager-trekk, juridiske bestillinger.
Eksamen-vinkel

Forvent spørsmål som ber deg begrunne et valg mellom relasjons-DB, dokument-DB, graf-DB, datalager. Gode svar nevner: type spørringer (oppslag vs sti vs aggregering), skala, skjema-stabilitet, og konsistenskrav (ACID vs eventually consistent).

Oppsummering

1NF er en valgsmulighet Strukturerte typer, arrays og multisets i SQL:1999+.
JSON i SQL er normalt JSONB-kolonner + GIN-indekser dekker det meste av "fleksibelt skjema".
3 V-er Volume · Velocity · Variety driver Big Data.
HDFS = bare et filsystem Hive, Spark, HBase ligger over.
MapReduce map → shuffle → reduce. Spark er etterfølgeren.
Fire NoSQL-familier KV, dokument, kolonne, graf — én er sjelden best for alt.
CAP under partisjon Velg C eller A. P er ikke valgfri.
BASE Basically Available · Soft state · Eventually consistent.
OLTP ≠ OLAP Transaksjoner vs analyse — ulik lagring, ulik schema.
Star-schema Fakta i midten, dimensjoner rundt. Snowflake = normaliserte dimensjoner.
Lake vs Warehouse Schema-on-read vs schema-on-write.
Default = RDBMS Bytt bare ved konkret behov.

Vil du teste deg selv på hele kapittelet samlet, finnes det en avsluttende quiz på kapittel-oversikten.