Skalerbar datalagring: SQL eller NoSQL
Velg mellom relasjonsdatabaser, nøkkel-verdi-lagre, dokumentdatabaser og wide-column-lagre basert på tilgangsmønstre, konsistens og krav til skala.
Skalerbar datalagring: SQL eller NoSQL er en gratis leksjon i DSA Interview Prep på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i DSA Interview Prep, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i DSA Interview Prep inneholder totalt 4 leksjoner.
Valg av lagring innebærer avveininger
Å velge en lagringsteknologi er en av de mest betydningsfulle beslutningene i systemdesign. Ingen database er best i alle sammenhenger — hver type er optimalisert for ulike tilgangsmønstre, konsistensgarantier og skalerings-egenskaper. Hvis du velger feil i produksjon, kan det føre til måneder med krevende migreringsarbeid.
I intervjuer undersøker intervjuere om du forstår de grunnleggende forskjellene og kan tilpasse en lagringsmotor til kravene i et problem. Spørsmålet er aldri «hvilken er best?», men «hvilken er best for akkurat denne arbeidsbelastningen?». Begrunn alltid valget med konkrete krav.
# Storage decision matrix summary
factors = [
'Data structure (tabular, documents, key-value, graph, time-series)',
'Read vs write ratio (read-heavy, write-heavy, balanced)',
'Query patterns (point lookups, range scans, aggregations, joins)',
'Consistency requirements (ACID vs eventual consistency)',
'Scale requirements (single node, sharding, global distribution)',
'Latency requirements (milliseconds vs microseconds)',
'Team familiarity and operational complexity',
]
print('Key factors for storage selection:')
for f in factors:
print(f' - {f}')Relasjonsdatabaser (SQL): styrker
Relasjonsdatabaser (PostgreSQL, MySQL, SQLite) lagrer data i tabeller med faste skjemaer og støtter ACID-transaksjoner — Atomicity, Consistency, Isolation, Durability. De er spesielt gode på komplekse spørringer med joins, aggregasjoner og filtre, noe som gjør dem ideelle for strukturerte data med veldefinerte relasjoner.
Viktige styrker: komplekse spørringer på tvers av flere tabeller via SQL, fremmednøkkelbegrensninger for dataintegritet, kraftig indeksering (B-tree, hash, full-text) og et modent økosystem med replikering og sikkerhetskopiering. Bruk SQL når dataene dine er sterkt relasjonelle, konsistens er avgjørende, og spørringene er komplekse og varierte.
# SQL excels at: complex queries, joins, transactions
# Example: find top 5 products by revenue this month
sql_query = '''
SELECT p.name, SUM(oi.quantity * oi.price) AS revenue
FROM orders o
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id
WHERE o.created_at >= DATE_TRUNC('month', NOW())
GROUP BY p.id, p.name
ORDER BY revenue DESC
LIMIT 5;
'''
print('SQL shines for relational queries with JOINs:')
print(sql_query)
print('ACID guarantees example (transfer $100 between accounts):')
transfer_sql = '''
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT; -- either both succeed or neither does
'''
print(transfer_sql)Utfordringer ved skalering av SQL
SQL-databaser skalerer vertikalt på en naturlig måte (større server, mer CPU/RAM), men horisontal skalering er komplisert. Lesereplikaer håndterer lesetunge arbeidsbelastninger ved å sende lesinger til replikanoder og skrivinger til primærnoden. Skrivegjennomstrømningen er imidlertid begrenset til én primærnode med mindre du legger til sharding.
Sharding partisjonerer data på tvers av flere DB-instanser ved hjelp av en shard-nøkkel (f.eks. user_id mod N). Dette gir skalerbarhet for skriving, men bryter joins og transaksjoner på tvers av shards — to av SQLs sterkeste funksjoner. De fleste webapplikasjoner vokser ut av SQL på én node ved rundt 5–10 TB data eller ~100K skriveoperasjoner per sekund.
# SQL scaling strategies
strategies = {
'Read replicas': {
'how': 'One primary (writes), multiple replicas (reads)',
'scales': 'Read throughput (10x+)',
'limit': 'Write throughput still bounded by single primary',
},
'Connection pooling (PgBouncer)': {
'how': 'Pool of persistent DB connections shared among app servers',
'scales': 'Connection count (PostgreSQL max ~500 connections)',
'limit': 'Does not increase query throughput',
},
'Horizontal sharding': {
'how': 'Partition rows by shard key across N database instances',
'scales': 'Both reads and writes (N×)',
'limit': 'Cross-shard joins and transactions broken; complex routing',
},
'CQRS': {
'how': 'Separate write model (SQL) from read model (denormalised/NoSQL)',
'scales': 'Optimise each path independently',
'limit': 'Eventual consistency between write and read models',
},
}
for strategy, info in strategies.items():
print(f'{strategy}:\n How: {info["how"]}\n Scales: {info["scales"]}\n Limit: {info["limit"]}\n')Nøkkel-verdi-lagre: Redis og DynamoDB
Nøkkel-verdi-lagre lagrer data som nøkkel → verdi-par, med O(1)-lesing og -skriving basert på nøkkelen. De gir avkall på fleksible spørringer til fordel for ekstrem ytelse og horisontal skalerbarhet. Redis (in-memory) oppnår mikrosekundlatens, mens DynamoDB (administrert) oppnår en ensifret latenstid målt i millisekunder, med automatisk skalering til hvilken som helst gjennomstrømning.
Bruk nøkkel-verdi-lagre til: lagring av økter, caching, feature flags, koblinger for URL-forkortere, handlekurver og rangeringstavler i sanntid. Ikke bruk dem når du trenger: komplekse spørringer, relasjoner mellom entiteter eller ad hoc-filtrering — du kan bare slå opp ved hjelp av en eksakt nøkkel.
# Key-value store use cases
kv_operations = {
'GET key': 'O(1) point lookup — the core operation',
'SET key value': 'O(1) insert or update',
'DEL key': 'O(1) delete',
'EXPIRE key ttl': 'Set time-to-live; key auto-deleted after ttl seconds',
'INCR key': 'Atomic increment — useful for counters and rate limiting',
'LPUSH/LRANGE': 'List operations — useful for queues and recent-items feeds',
'ZADD/ZRANGE': 'Sorted set — leaderboards, rate limiting with sliding window',
}
print('Redis operation set:')
for op, desc in kv_operations.items():
print(f' {op:25s}: {desc}')
print('\nDynamoDB vs Redis:')
print(' Redis: microsecond latency, in-memory, needs persistence config')
print(' DynamoDB: single-digit ms, managed, auto-scaling, durable by default')Dokumentlagre: MongoDB
Dokumentlagre (MongoDB, Couchbase) lagrer data som JSON-lignende dokumenter, noe som gir fleksible skjemaer — feltene kan variere mellom dokumenter i samme samling. De støtter indeksering på alle felt og relativt innholdsrike spørringer (filtre, projeksjoner, aggregasjoner), selv om transaksjoner på tvers av flere dokumenter er mer begrensede enn i SQL.
Dokumentlagre passer for applikasjoner der: dataformen varierer fra entitet til entitet (brukerprofiler med ulike attributter), rask utvikling av skjemaet forventes (oppstartsbedrifter som ofte endrer datamodeller), eller lesemønstrene hovedsakelig består av å hente hele entiteter fremfor å koble sammen tabeller.
# MongoDB document example
user_doc = {
'_id': 'user123',
'name': 'Alice',
'email': 'alice@example.com',
'preferences': {
'theme': 'dark',
'language': 'en',
'notifications': ['email', 'push']
},
'addresses': [
{'type': 'home', 'city': 'Berlin', 'country': 'DE'},
{'type': 'work', 'city': 'Munich', 'country': 'DE'}
],
'subscription_tier': 'pro',
# Note: not all users have all fields -- flexible schema!
}
import json
print('Document structure (flexible schema):')
print(json.dumps(user_doc, indent=2))
print('\nDocument store strengths:')
print(' - Nested/array fields without joins')
print(' - Flexible schema (different fields per document)')
print(' - Scales horizontally by sharding on _id')Wide-column-lagre: Cassandra
Wide-column-lagre (Apache Cassandra, HBase) lagrer data i rader og kolonner, men tillater at hver rad har et forskjellig sett med kolonner. De er utformet for svært høy skrivegjennomstrømning fordelt på mange noder, med eventual konsistens som standard. Cassandra oppnår lineær skalerbarhet for skriving — dobbelt så mange noder dobler skrivegjennomstrømningen.
Avveiningen er at spørringer må utformes rundt partisjonsnøkkelen. Du kan ikke filtrere eller sortere effektivt på vilkårlige kolonner — først må du definere spørringsmønsteret og deretter utforme tabellen slik at den passer. Dette er det motsatte av SQLs tilnærming «utform dataene først, og skriv deretter en hvilken som helst spørring».
# Cassandra table design for time-series events
# Design around the query: 'give me all events for user X, most recent first'
cassandra_table = '''
CREATE TABLE user_events (
user_id UUID,
event_time TIMESTAMP,
event_type TEXT,
metadata MAP<TEXT, TEXT>,
PRIMARY KEY (user_id, event_time)
) WITH CLUSTERING ORDER BY (event_time DESC);
-- Query (matches partition key exactly):
SELECT * FROM user_events WHERE user_id = ? LIMIT 100;
'''
print('Cassandra wide-column design:')
print(cassandra_table)
print('Properties:')
print(' - user_id = partition key (all rows for one user on same node)')
print(' - event_time = clustering key (sorted within partition)')
print(' - Very fast writes: append-only, no locking')
print(' - Cannot query by event_type alone (no partition key)')CAP-teoremet: konsistens, tilgjengelighet og partisjonstoleranse
CAP-teoremet sier at et distribuert system høyst kan garantere to av følgende: Consistency (konsistens: hver lesing returnerer den nyeste skrivingen), Availability (tilgjengelighet: hver forespørsel får et svar som ikke er en feil), og Partition tolerance (partisjonstoleranse: systemet fortsetter å fungere selv ved nettverkspartisjoner).
Siden nettverkspartisjoner alltid oppstår i distribuerte systemer, er det reelle valget mellom CP (prioriterer konsistens, og kan avvise forespørsler under en partisjon) og AP (prioriterer tilgjengelighet, og kan returnere foreldede data). SQL-databaser er vanligvis CP; Cassandra og DynamoDB er AP (eventual konsistens som standard). Redis Cluster er CP.
# CAP theorem applied to common databases
databases = {
'PostgreSQL (single node)': {'C': True, 'A': True, 'P': False, 'note': 'Not distributed; CA'},
'PostgreSQL (multi-AZ)': {'C': True, 'A': False, 'P': True, 'note': 'CP: primary fails over, brief downtime'},
'MySQL Cluster': {'C': True, 'A': False, 'P': True, 'note': 'CP'},
'Cassandra': {'C': False, 'A': True, 'P': True, 'note': 'AP: eventual consistency default'},
'DynamoDB (default)': {'C': False, 'A': True, 'P': True, 'note': 'AP: eventual consistency'},
'DynamoDB (strong read)': {'C': True, 'A': False, 'P': True, 'note': 'CP: strongly consistent reads'},
'Redis Cluster': {'C': True, 'A': False, 'P': True, 'note': 'CP'},
'MongoDB (default)': {'C': True, 'A': False, 'P': True, 'note': 'CP: reads from primary'},
}
for db, caps in databases.items():
c_str = 'C' if caps['C'] else '-'
a_str = 'A' if caps['A'] else '-'
p_str = 'P' if caps['P'] else '-'
print(f'{db:35s} [{c_str}{a_str}{p_str}] {caps["note"]}')Et rammeverk for valg av lagring
Et praktisk rammeverk for valg av lagring i intervjuer:
- Trenger du ACID-transaksjoner? → Relasjonsdatabase (PostgreSQL, MySQL)
- Trenger du oppslag på under ett millisekund eller caching? → Nøkkel-verdi-lager (Redis)
- Trenger du et fleksibelt skjema eller dokumentorienterte data? → Dokumentlager (MongoDB)
- Trenger du svært høy skrivegjennomstrømning (>100K/sek.) med tidsserier eller hendelsesdata? → Wide-column-lager (Cassandra)
- Trenger du global distribusjon med administrert skalering? → DynamoDB eller Cosmos DB
- Trenger du graftraversering? → Grafdatabase (Neo4j)
# Decision tree in code form
def choose_storage(needs_acid, high_write_throughput, flexible_schema,
sub_ms_latency, graph_queries, global_scale):
if sub_ms_latency:
return 'Redis (in-memory key-value)'
if graph_queries:
return 'Neo4j (graph database)'
if needs_acid:
return 'PostgreSQL / MySQL (relational)'
if high_write_throughput and not flexible_schema:
return 'Cassandra (wide-column, write-optimised)'
if flexible_schema:
return 'MongoDB (document store)'
if global_scale:
return 'DynamoDB or Cosmos DB (managed global KV/document)'
return 'PostgreSQL (safe default for most web apps)'
# Example scenarios
scenarios = [
{'needs_acid': True, 'high_write_throughput': False, 'flexible_schema': False,
'sub_ms_latency': False, 'graph_queries': False, 'global_scale': False},
{'needs_acid': False, 'high_write_throughput': True, 'flexible_schema': False,
'sub_ms_latency': False, 'graph_queries': False, 'global_scale': False},
{'needs_acid': False, 'high_write_throughput': False, 'flexible_schema': False,
'sub_ms_latency': True, 'graph_queries': False, 'global_scale': False},
]
for s in scenarios:
print(f'{choose_storage(**s)}')Polyglot persistence: bruk av flere lagre
Produksjonssystemer bruker sjelden én enkelt database til alt. Polyglot persistence betyr å bruke riktig lagringsteknologi for hver del av systemet. En typisk webapplikasjon kan bruke: PostgreSQL for autoritative bruker- og ordredata, Redis for lagring av økter og caching, Elasticsearch for fulltekstsøk, S3 for fillagring og Cassandra for hendelseslogger og analyse.
Avveiningen er at driftskompleksiteten øker med hver databasetype. Teamet må vedlikeholde, overvåke og sikkerhetskopiere flere systemer. Begrunnelsen for designet er at ytelses- og skaleringsgevinsten ved å tilpasse hver arbeidsbelastning til riktig lagringsteknologi oppveier driftskostnaden i stor skala.
# Polyglot persistence in an e-commerce system
components = {
'User accounts, orders, payments': {
'storage': 'PostgreSQL',
'reason': 'ACID transactions (payment integrity), complex queries',
},
'Product catalogue': {
'storage': 'MongoDB or PostgreSQL with JSONB',
'reason': 'Flexible product attributes vary by category',
},
'Session tokens': {
'storage': 'Redis (with TTL)',
'reason': 'O(1) lookup, automatic expiry, high throughput',
},
'Product search': {
'storage': 'Elasticsearch',
'reason': 'Full-text search, faceted filtering, relevance scoring',
},
'Activity/event log': {
'storage': 'Cassandra or Kafka + S3',
'reason': 'High write throughput, append-only, time-series queries',
},
'Product images / videos': {
'storage': 'S3 + CloudFront CDN',
'reason': 'Cheap object storage, global distribution via CDN',
},
}
for component, info in components.items():
print(f'{component}:\n {info["storage"]}: {info["reason"]}\n')Indekseringsstrategi på tvers av lagringstyper
Alle lagringssystemer bruker indekser for å gjøre lesinger raskere, på bekostning av langsommere skrivinger og ekstra lagringsplass. Det er avgjørende å forstå indeksering på tvers av lagringstyper i systemdesign:
- SQL: B-tree-indeks på alle kolonner; sammensatte indekser for spørringer med flere kolonner; covering-indekser for å unngå oppslag i tabellen
- MongoDB: indeks på alle felt; sammensatte indekser; TTL-indekser for automatisk utløp
- Cassandra: bare partisjonsnøkkelen og clustering-kolonner indekseres innebygd; sekundærindekser er kostbare
- Redis: sorterte sett som indekser for områdespørringer; ingen tradisjonell indeksering er nødvendig for nøkkel-verdi-lagre
# Indexing examples across storage types
# PostgreSQL: B-tree composite index
postgres_index = '''
CREATE INDEX idx_orders_user_created
ON orders(user_id, created_at DESC);
-- Optimises: SELECT * FROM orders WHERE user_id=? ORDER BY created_at DESC
'''
# MongoDB: compound index
mongo_index = '''
db.products.createIndex({ category: 1, price: -1 })
// Optimises: db.products.find({category:'Electronics'}).sort({price:-1})
'''
# Cassandra: cluster key ordering (built into table design)
cassandra_index = '''
-- No separate index needed; clustering key IS the index:
PRIMARY KEY (user_id, event_time) WITH CLUSTERING ORDER BY (event_time DESC)
'''
print('PostgreSQL:', postgres_index)
print('MongoDB:', mongo_index)
print('Cassandra:', cassandra_index)SQL eller NoSQL i intervjuer: hva du bør si
Når du blir spurt «SQL eller NoSQL?» i et systemdesignintervju, bør du aldri svare med bare ett ord. Følg i stedet denne strukturen:
- Beskriv arbeidsbelastningen: «Dette er lesetungt med kompleks filtrering, så …»
- Oppgi kravet: «Vi trenger sterk konsistens for finansielle transaksjoner, så …»
- Oppgi valget: «Jeg ville brukt PostgreSQL med lesereplikaer»
- Oppgi avveiningen: «Avveiningen er at horisontal skalering av skriving krever sharding, noe som tilfører kompleksitet»
- Nevn et alternativ: «Hvis skrivebelastningen var høyere, kunne vi vurdert DynamoDB»
# Sample answer structure for 'SQL or NoSQL?'
def answer_storage_question(workload, consistency_need, scale):
print(f'Workload: {workload}')
print(f'Consistency: {consistency_need}')
print(f'Scale: {scale}')
print()
if 'financial' in workload.lower() or consistency_need == 'strong':
choice = 'PostgreSQL (ACID, strong consistency)'
tradeoff = 'Horizontal write scaling requires sharding'
alternative = 'Google Spanner for global transactions'
elif 'event' in workload.lower() or 'log' in workload.lower():
choice = 'Cassandra (high write throughput, time-series)'
tradeoff = 'Eventual consistency; queries limited to partition key'
alternative = 'Kafka + S3 for long-term event archival'
else:
choice = 'DynamoDB (managed, auto-scale, low latency)'
tradeoff = 'Limited query flexibility; cross-item transactions limited'
alternative = 'PostgreSQL if complex queries emerge'
print(f'Choice: {choice}\nTrade-off: {tradeoff}\nAlternative: {alternative}')
answer_storage_question('Social media feed', 'eventual', '10M users')Hurtigsjekk
Test forståelsen din av begrepene Data Structures & Algorithms — Coding Interview Prep fra denne leksjonen.
Oppsummering av leksjonen
I denne leksjonen lærte du: SQL-databaser tilbyr ACID-transaksjoner og komplekse spørringer, men har vanskeligheter med å skalere skriving, mens NoSQL-databaser bytter bort konsistens eller fleksible spørringer for ekstrem skala og tilgjengelighet, CAP-teoremet tvinger distribuerte systemer til å velge mellom konsistens og tilgjengelighet under nettverkspartisjoner, og produksjonssystemer bruker vanligvis polyglot persistence — hver arbeidsbelastning kobles til riktig lagringsmotor. Deretter skal vi se på cachinglag, CDN-er og lastbalansering for å skalere lesetunge systemer ytterligere.
Lær deg Python med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 30
- Leksjoner
- 120
Ofte stilte spørsmål
Er leksjonen «Skalerbar datalagring: SQL eller NoSQL» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien DSA Interview Prep, inkludert «Skalerbar datalagring: SQL eller NoSQL», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i DSA Interview Prep inneholder totalt 4 leksjoner.
Hva lærer jeg i «Skalerbar datalagring: SQL eller NoSQL»?
Velg mellom relasjonsdatabaser, nøkkel-verdi-lagre, dokumentdatabaser og wide-column-lagre basert på tilgangsmønstre, konsistens og krav til skala. Du øver på DSA Interview Prep med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med DSA Interview Prep?
Ingen tidligere erfaring er nødvendig. DSA Interview Prep på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.
Hvor lang tid tar leksjonen «Skalerbar datalagring: SQL eller NoSQL»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne DSA Interview Prep-leksjonen?
Ja. Alle DSA Interview Prep-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Rammeverk for systemdesignintervjuet
- Skalerbar datalagring: SQL eller NoSQL
- Caching, CDN-er og lastbalansering
- Design Rate Limiter og Design Twitter Feed