Databaser er et tema det er skrevet bunkevis av tykke bøker om, men som kan være temmelig forvirrende for både ferske og litt mer erfarne utviklere.
Det finnes en masse forskjellige typer databaser som egner seg til ulike formål. Logger du deg på skytjenester som AWS, Google Cloud eller Azure skorter det ikke på valgmuligheter, men det er ikke alltid intuitivt hva du bør velge eller hvorfor.
I et forsøk på å bli litt klokere, ba vi utvikler Anders Njøs Slinde i Variant om å gi oss et grunnkurs i databaser.
Og vi stilte de dumme spørsmålene, så du slipper!
– Anders, hva er en database?
– En database er ganske enkelt et sted man lagrer data på en organisert måte. En skuff med kort sortert alfabetisk er en form for database, også kalt et kartotek.
– Det samme kan man si om alt fra CSV-filer til databaseløsningene som blir tilbudt av store leverandører som Microsoft og Amazon.
Server Components: - Rimelig ferske greier
– Hva er forskjellen på en database som bruker SQL, og såkalte "noSQL"-databaser?
– Det er et godt spørsmål, og en kilde til mye forvirring. For å svare må jeg først forklare hva en relasjonsdatabase er.
– En relasjonsdatabase er en database der dataene er lagret i tabeller med rader og kolonner. Tenk regneark som for eksempel Excel. I en relasjonsdatabase har hver tabell en primærnøkkel, og tabellene kan ha en relasjon til en andre tabeller ved å ha en kolonne med verdien til nøkkelen i en annen tabell. Denne kolonnen blir kalt en fremmednøkkel. Det er et ganske enkelt konsept, men å modellere en god relasjonsdatabase kan fort bli vanskelig og være veldig tidkrevende.
– Man må prøve å finne en balanse mellom hvor mange tabeller en skal dele dataene sine inn i, og hvor vanskelig det da blir å hente ut og sammenstille dataene i etterkant.
– Relasjonsdatabaser bruker ofte en dialekt av Structured Query Language (SQL) for å manipulere eller hente ut data.
«Nå synes jeg personlig at noSQL som begrep er utdatert.»
– Begrepet noSQL blir brukt for å snakke om alt som ikke er en relasjonsdatabase. Det kom mange nye typer databaser i en vending, og det var vel et behov for å skille seg ut, samtidig som det ikke var noen gode samlebetegnelser ennå. Nå synes jeg personlig at noSQL som begrep er utdatert og vi burde prøve å være mer spesifikke når vi snakker om databaser.
– Nå finnes det såpass mange dokumentdatabaser, key-value stores, grafdatabaser og vektordatabaser, så å bruke begrepet noSQL når man snakker om de synes jeg blir for lite spesifikt. Dokumentdatabaser som MongoDB, grafdatabaser som Neo4j og key-value stores som Redis er alle såkalt noSQL, men er tre helt forskjellige databaser med helt forskjellige bruksområder.
– Det er også noen som prøver å lansere begrepet "NewSQL" for databaser som ikke er relasjonsdatabaser, men som likevel bruker SQL.
– Har du eksempler på noen mye brukte databaser?
– Vi kan ikke snakke om databaser uten å nevne PostgreSQL.
– PostgreSQL er databaseverdenens potet, og bør etter min mening være standardvalget når man skal velge database. Det som gjør PostgreSQL unik er at den er open source, og dermed tilgjengelig hos så og si alle skyleverandører. Den er lett å bruke siden SQL-dialekten den bruker er veldig nærme SQL-standarden, og det finnes drivere for de aller fleste programmeringsspråk.
«PostgreSQL er databaseverdenens potet, og bør etter min mening være standardvalget når man skal velge database.»
– I løsningen jeg jobber på nå så bruker vi dokumentdatabasen MongoDB. Det vil si at i stedet for å definere tabeller og relasjoner mellom dem, så dytter vi hele dokumenter inn i databasen i form av BSON (BSON ser ut som JSON).
– Vi trenger ikke å sette opp noe databaseskjema på forhånd slik som vi må gjøre i en relasjonsdatabase. Det er dataene som blir fokuset, og ikke relasjonene. Fordelene med en dokumentdatabase er at man kan iterere raskt, man trenger ikke bruke like mye tid på å planlegge og tenke ut hvordan dataene ser ut på forhånd. Ofte er det enklere å jobbe med dokumentdatabaser siden dokumentene ligner mer på domenemodellene enn det tabellene i relasjonsdatabasen din ville gjort.
– MongoDB har et veldig fleksibelt system for indeksering, som gjør at man kan gjøre det raskt å hente ut data uten å måtte redesigne databaseoppsettet sitt.
– Redis er en database som er ulik fra de forrige igjen. Denne er en minnebasert key-value-database, som ofte blir brukt til caching eller som en messagebroker. Redis har veldig god ytelse, men persisterer ikke til disk som standardvalg (man kan velge å skru på diskpersistens, men dette går på bekostning av ytelsen).
Kotlin vs. Java: - Mye unødvendig boilerplate
– Databaser har gjerne ulike "spørrespråk", som SQL. Fortell litt om det!
– Yep. SQL er et relativt enkelt deklarativt språk som er laget for å være et databasespørrespråk. Det finnes en ISO-standard for SQL, også finnes det utallige dialekter.
– Eksempel:
SELECT * FROM Users WHERE email='webmaster@variant.no'
– Denne henter ut alle users som har den gitte epostaddressen.
– MongoDb har sitt eget spørrespråk, MongoDb Quey Language (MQL). MQL minner mye om JavaScript, og tilsvarende spørring i MongoDb blir:
db.Users.find({ email : "webmaster@variant.no" })
– Du har også en masse "spesial-databaser", hva brukes de til?
Grafdatabaser:
– Grafdatabaser har egentlig bare to komponenter: en node og en kant. En node inneholder informasjon om en entitet, og en kant forteller oss om relasjonen mellom to noder.
– Grafdatabaser er veldig ofte brukt til sosiale nettverk, slikt som Facebook, Twitter og LinkedIn for eksempel. I mange tilfeller er relasjonen (både type og data) mellom noder viktigere enn nodene selv. I et sosialt nettverk er det like viktig å vite hvem du er kollega eller i slekt med, som informasjon om personen.
– En sterk side ved grafdatabaser er å hente data fra flere forskjellige type noder. I en relasjonsdatabase vil en type node være en tabell og skal man ha data fra flere tabeller vil man måtte bruke “joins”, og med mange tables vil dette bli en veldig kompleks query. Man vil ikke ha dette problemet i graf, da alle data er koblet sammen via kanter.
Objektdatabaser:
– Objekt-databaser er nært knyttet til objekt-orienterte språk. De lagrer dataene som objekter i databasen og ikke som en tabell eller dokument. Man trenger ingen mapping når man skal lese eller skrive til databasen, de er allerede lagret som objekter. Siden databasestrukturen er veldig lik strukturen i språket vil koden ofte være lettere å lese og jobbe med.
– Objekt-databaser er optimalisert for høy hastighet og rask kalkulering. Objekt-databaser kan bli brukt til for eksempel 3D-modellering og astronomi. Det er viktig å presisere at bare fordi man bruker et objektorientert språk så bruker man ikke nødvendigvis en objekt-database.
– Objekt-databaser blir ofte sammenblandet med dokumentdatabaser, men dokumentdatabaser bruker JSON eller andre serialiseringsformater, mens objekt-databaser lagrer objektene mer direkte.
Mystiske .NET MAUI forklart: - Ikke for alle
Key-value-databaser:
– Key-value-databaser lagrer dataene som key-value-format. Slike databaser er optimalisert for rask lesing og skriving. Key-value databaser passer veldig bra til real-time random data access, slik som brukersesjoner innenfor finans eller gaming.
– Key-value-databaser er designet for å skalere horisontalt (flere instanser) og passer bra til tjenester som har mange brukere samtidig, slik som handlekurvene i nettbutikker.
In-memory-databaser:
– In-memory-databaser er databaser som holder alle dataene i minnet. Siden alle dataene er i minnet trenger den færre cpu-instruksjoner og trenger ikke å hente data fra disk.
– In-memory databaser passer til alt som krever lav responstid, real-time analyse og høy throughput. Dette kan være områder som finans, gaming og reise. Her er det viktig å huske på at mange databaser kan være en in-memory, for eksempel grafdatabasen Memgraph og key-value databasen Redis er begge in-memory-databaser.
Vektordatabaser:
– En vektordatabase lar deg lagre data slik som tekst, bilder eller lyd som vektorer. En vektor er i tilfellet her bare en liste med tall, som disse tekstene eller bildene eller lignende er generert ut fra. Da er naturlig nok spørsmålet, hvorfor ikke bare lagre tekst eller bilder i opprinnelig format? Hvorfor skal de lagres som lister med tall?
«En vektordatabase er ofte et veldig godt supplement til store språkmodeller.»
– Fordi typisk sett er disse vektorene generert av en maskinlæringsmodell som oversetter dataene, om det er tekst eller bilder, til et mange-dimensjonelt vektorrom. Slike vektorer kalles vanligvis en "embedding". Her kommer styrken til vektor-databasen inn. Hvis du har en vektordatabase med bilder, så kan du gi den en input, altså en vektor av et bilde, og spørre den hvilke andre bilder ligger i nærheten av dette bildet i det mange-dimensjonelle vektorrommet.
– Med andre ord kan man spørre databasen om hvilke bilder i databasen som "ligner" på et gitt bilde. Dette fungerer som sagt også for andre type data. En vektordatabase er ofte et veldig godt supplement til store språkmodeller (LLMs), fordi LLMs ikke har kunnskap utenom det den har blitt opplært på. En vektordatabase kan på sett og vis fungere som et langtidsminne for LLM-en, og du som utvikler velger hva den skal "huske" der. For å lære mer om hvordan vektordatabaser kan brukes sammen med språkmodeller se denne blogposten.
– Native kan være dyrt og unødvendig, mener Flutter-elsker
– Hvor avgjørende er det å velge riktig database til et gitt formål?
– Det er veldig mange avveininger man må gjøre for å treffe riktig på dette, så her tør jeg ikke komme med noe generelt svar. For eksempel så er dokumentdatabaser som MongoDb veldig gode på horisontal skalering av store datamengder, gitt at man kan godta eventual consistency, det vil si at det kan ta litt tid før en skriveoperasjons speiles ut til alle brukere.
– Hvis man trenger dataene med en gang etter at de er skrevet så er som regel en relasjonsdatabase bedre. Trenger man kun oppslag på nøkkel? Da er key-value stores perfekt og har uslåelig ytelse og skalerbarhet, men hvis man trenger fuzzy-search har man malt seg inn i et hjørne.
– Trenger man fuzzy search? Da bør man vurdere ElasticSearch eller Solr, men disse kan være krevende å få satt opp og de når en øvre grense på ytelse og horisontal skalering.
«Valg av database er et arkitekturvalg som er veldig vanskelig og dyrt å endre etter at kodingen har startet.»
– Hvis man vil lære mer om disse avveiningene kan man starte med å lese seg opp på CAP-theoremet. Dette theoremet går ut på at man kan kun velge to egenskaper av consistency, availability og partition tolerance når man designer et distribuert system. Dette er veldig relevant når man skal lagre data på tvers av flere datasenter.
– Valg av database er et arkitekturvalg som er veldig vanskelig og dyrt å endre etter at kodingen har startet. Dette gjør det også viktig å ikke tenke for avansert mener jeg, men å velge noe velprøvd som er enkelt å drifte og enkelt å bruke riktig.
– Verdt å merke seg at når datamengdene er såpass små at man kan klare seg med en single instans av en velprøvd database blir avveiningene rundt skalerbarhet litt overflødige, og det begynner å handle mer om hvordan man liker å jobbe og personlige preferanser.
– Kanskje en brannfakkel å påpeke men siden vi bor i et lite land så er det ikke så ofte vi norske utviklere møter på problemer som krever noe veldig fancy på databasefronten, desverre og heldigvis.
– Hvordan håndterer man sikkerheten til en database?
– Her er nettverkssikkerhet viktig. Det er ingen grunn til å eksponere databasen sin på internett, så sett opp nettverket slik at kun applikasjonen sitt kjøremiljø har tilgang til den.
– Jeg vil også sterkt anbefale å bruke certifikater (TLS) både for å kryptere trafikken, og for å verifisere identiteten til de som kobler seg til databasen. Det begynner heldigvis å bli gode defaults hos skyleverandørene på dette, så hvis man setter opp både database og applikasjon i for eksempel Azure så er dette ganske enkelt å få gjort riktig.
- Du bør ha svært gode grunner, om du ikke vil deploye til skyen
– Hvordan har skytjenester og distribuerte systemer endret hvordan man bruker databaser?
– Det jeg tenker på først og fremst her er at det har blitt veldig enkelt å sette opp en database. Man kan bare trykke seg inn i Azure eller AWS og få en hvilken som helst database satt opp på få minutter.
– Dette har gjort det mye enklere å velge en database som passer til det man skal lage.
– Distribuerte systemer og mikrotjenester har gjort at utviklere ofte må kunne forholde seg til flere forskjellige databaseteknologier i løpet av en arbeidsdag. Kanskje har man brukerdatabasen i postgres, produktene i mongodb og caching i redis.
«Distribuerte systemer og mikrotjenester har gjort at utviklere ofte må kunne forholde seg til flere forskjellige databaseteknologier i løpet av en arbeidsdag.»
– Og så har vi de mystiske ORM-ene, hva er det?
– Prisma er et godt eksempel på en ORM (Object Relational Mapping). Med prisma så kan man definere hvilke objekter man vil lagre i databasen. Prisma genererer databasemigreringer som man kjører for å sette opp eller oppdatere databasen med tabeller og kolonner.
– Så genererer Prisma typescript-typer som samsvarer med dette oppsettet, slik at man kan hente ut og lagre objekter uten å måtte skrive SQL.
– Det er fornuftig å bruke ORM-er når man skal jobbe med relativt enkle data og forholdsvis enkle operasjoner. For et REST-API som stort sett gjør create read update delete (CRUD) er en ORM perfekt.
– En vanlig felle å gå i med ORM-er er at man glemmer at det er en database bak der. Dette kan føre til at man skriver kode som genererer veldig mange spørringer eller veldig ineffektive spørringer. Hvis man har veldig avanserte datastrukturer, for eksempel trestrukturer, så vil en ORM slite litt, og man bør skrive SQL-en for uthenting selv.
Nå bruker han Remix til alt: – Det løser mange vanskelige ting med React
– Er det noe annet kode24-leserne bør vite om databaser?
– Det at det nå er mye lettere og vanligere å ta i bruk flere forskjellige databaseteknologier har gjort at det skjer mye innovasjon på feltet for tiden.
– Det dukker stadig opp nye interessante databasekonsepter. CloudFlare for eksempel har lansert flere serverløse databaser, der den som stikker seg mest ut er et konsept de har kalt Durable Objects. Her kan man opprette og oppdatere objekter på en nøkkel og objektene blir automatisk persistert ut i CloudFlare sitt nettverk slik at man aksesseres fra hvor som helst i verden "med en gang".
– Det er et veldig interessant konsept for chat, multiplayerspill eller andre ting der man ønsker både konsistens og raske oppdateringer.
«Da jeg første leste om SpacetimeDB klarte jeg ikke å bestemme meg for om det var sinnsykt eller genialt.»
– Et annet interessant konsept er SpacetimeDB fra Clockwork Labs. Denne databasen lar deg kompilere koden til en WebAssembly-modul som lastes opp til databasen. Brukerene kobler seg direkte til databasen, også kjøres applikasjonslogikken rett i databasen.
– Da jeg første leste om SpacetimeDB klarte jeg ikke å bestemme meg for om det var sinnsykt eller genialt. Med andre ord er det mye spennende som skjer på databasefeltet for tiden, så det er bare å henge med!
– Og så vil jeg si takk til Inge Hegge og Christian Brevik som hjalp meg å svare på spørsmålet om spesial-databaser!