Lagring og indekser
Hvor data faktisk ligger — fra rotende disk til en blokk i bufferet, og hvordan B+-treet finner riktig rad på 3 oppslag.
Hvorfor bryr vi oss om hvor dataen ligger?
Et SQL-spørsmål som SELECT * FROM Employee WHERE empno = 4711 ser uskyldig ut. Bak kulissene må DBMS-en finne én rad blant millioner. Det kan ta 1 millisekund eller 10 sekunder — forskjellen ligger i hvordan dataene er lagret på disken og hvilke indekser som finnes.
RAM-aksess tar ~100 nanosekunder. Et tilfeldig HDD-oppslag tar ~10 millisekunder — fem størrelsesordener tregere. Så regelen er enkel: tell antall blokker du må lese fra disken. Det er nesten alltid den dominerende kostnaden.
Tenk på diskaksess som å sende en bud til arkivet i kjelleren — og RAM som å åpne en bok som ligger på pulten. Indekser er kort sagt smarte triks for å sende færrest mulig bud.
Fra device til felt
Hele kapittelet henger på dette ene bildet. Hver «boks» kjenner bare boksene umiddelbart over og under seg. SQL-laget snakker om rader; lagringslaget snakker om blokker. Resten av kapittelet handler om hvordan disse to verdenene møtes.
Tolv ord som låser opp kapittelet
Hvis du forstår disse 12, har du forstått kjernen. Resten er detaljer.
Blokk (page)
Den minste enheten DBMS-en leser eller skriver. Typisk 4–32 KiB. All koblingen mellom disk og minne skjer i blokker — aldri på rad-nivå.
Record / RID
En rad lagret som bytes. RID = (BlockId, slot) er den faste pekeren som indekser bruker.
Slot directory
En vektor på slutten av blokken som peker inn i blokken. Lar deg flytte recordene uten å ugyldiggjøre RID-ene.
Buffer pool
RAM-arealet hvor blokker holdes mens de er i bruk. Hash-indeksert på BlockId. Erstatningsstrategi: LRU, MRU eller clock.
Heapfil
Tabell uten orden. Insert er O(1), søk er O(N). Brukes typisk når det finnes en separat indeks ved siden av.
Hashfil
Konstant-tid likhetsoppslag. Statisk hashing får overflow-problemer; extendible hashing løser det med en directory.
B+-tre
Balansert flerveistre med høy fanout. Alle data ligger i bladene; interne noder er bare guide. Bladene er lenket sammen for raske range-scans.
Clustered indeks
Radene i tabellen er fysisk sortert etter indeksnøkkelen. Maks én per tabell. Drastisk raskere for range-spørringer.
Unclustered indeks
Indeksen peker inn i en separat heapfil. Kan ha mange per tabell, men hver match krever ekstra blokkaksess.
Sparse vs dense
Dense = én indekspost per record. Sparse = én per blokk (kun mulig på clustered data). Sekundærindekser er alltid dense.
Fanout
Hvor mange barn en intern node har. Høyere fanout → færre nivåer → færre disk-I/O per oppslag.
Fill degree
Statistisk 2/3 i et B+-tre. Når du regner kapasitet i en oppgave: floor(blokk · 2/3 / recsize).
log200(1 000 000) ≈ 2.6, dvs. 3 nivåer i selve treet. Hvis indeksen er unclustered trenger vi i tillegg én aksess i heapfilen for selve raden — totalt 4. Hvis den er clustered ligger raden allerede i bladet — 3.
Utforsk kapittelet
Kapittelet er delt i to halvdeler. Begynn med 6A — du må forstå hvordan en rad ligger i en blokk før indekser gir mening.
Hovedkilde: lagring.pdf + Bratsbergs notater kap. 1–11. Læreboka dekker ikke lagringsdelen — disse to filene er pensum.
Et bilde du må kunne tegne
På eksamen må du kunne resonnere om antall blokk-aksesser. Skissen under gir deg de fire vanligste lagringsalternativene side om side.
Når du regner kostnaden av en spørring, gjør det alltid for hver av de fire alternativene over og sammenlikn — det er nettopp det Bratsberg gjør i kapittel 12.
Helhetsspørsmål
12 spørsmål som dekker hele kapittelet. Detaljerte spørsmål om lagring og B+-trær finner du på de respektive underkapitlene.
floor(4096/80) = 51. Antall blokker: ceil(1 000 000/51) = 19 608. Uten indeks må vi gjøre full scan, men i snitt finner vi raden halvveis: ~9804 blokker. (Hvis kolonnen er unik kan vi stoppe på den treffes; hvis ikke, må vi skanne alt: ~19 608.)WHERE age > 50, mens en B+-tree-indeks håndterer det effektivt?ceil(N / floor(blokkstørrelse · 2/3 / recsize)). Eksempel: 4 KiB blokk, 120-byte records → floor(4096 · 2/3 / 120) = 22 records per blokk.WHERE empno > 90000 hvor 20 % av radene matcher — hvorfor kan en full table scan faktisk være raskere?Order(orderId, customerId, date, total). Spørringene er hovedsakelig WHERE customerId = ? AND date BETWEEN ? AND ?. Hvilken indeks anbefaler du, og hvorfor er rekkefølgen viktig?