0Pricing
DSA Interview Prep · Pelajaran

Penyimpanan Data Skalabel: SQL vs NoSQL

Pilih antara basis data relasional, penyimpanan key-value, basis data dokumen, dan penyimpanan kolom lebar berdasarkan pola akses, konsistensi, dan kebutuhan skala

Penyimpanan Data Skalabel: SQL vs NoSQL adalah pelajaran DSA Interview Prep gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar DSA Interview Prep, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus DSA Interview Prep mencakup 4 pelajaran total.

Pilihan Penyimpanan Merupakan Kompromi

Memilih penyimpanan data merupakan salah satu keputusan paling menentukan dalam desain sistem. Tidak ada basis data yang selalu terbaik — setiap jenis dioptimalkan untuk pola akses, jaminan konsistensi, dan karakteristik skala yang berbeda. Kesalahan dalam memilih dapat menyebabkan pekerjaan migrasi yang menyakitkan selama berbulan-bulan di lingkungan produksi.

Dalam wawancara, pewawancara menguji apakah Anda memahami perbedaan mendasar dan dapat mencocokkan mesin penyimpanan dengan persyaratan suatu masalah. Pertanyaannya bukanlah “mana yang lebih baik?”, melainkan “mana yang lebih baik untuk beban kerja khusus ini?” Selalu sertakan persyaratan spesifik sebagai alasan pilihan Anda.

# 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}')

Basis Data Relasional (SQL): Keunggulan

Basis data relasional (PostgreSQL, MySQL, SQLite) menyimpan data dalam tabel dengan skema tetap dan mendukung transaksi ACID — Atomisitas, Konsistensi, Isolasi, Durabilitas. Basis data ini unggul dalam kueri kompleks dengan penggabungan, agregasi, dan penyaringan, sehingga ideal untuk data terstruktur dengan hubungan yang terdefinisi dengan baik.

Keunggulan utama: kueri kompleks pada banyak tabel melalui SQL, batasan kunci asing untuk menjaga integritas data, pengindeksan yang kuat (B-tree, hash, teks lengkap), serta ekosistem matang dengan replikasi dan pencadangan. Gunakan SQL ketika data Anda sangat relasional, konsistensi sangat penting, dan kuerinya kompleks serta beragam.

# 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)

Tantangan Penskalaan SQL

Basis data SQL secara alami melakukan penskalaan secara vertikal (server yang lebih besar, CPU/RAM yang lebih banyak), tetapi penskalaan horizontalnya kompleks. Replika baca menangani beban kerja yang didominasi pembacaan dengan mengarahkan operasi pembacaan ke simpul replika dan operasi penulisan ke simpul utama. Namun, laju penulisan terbatas pada satu simpul utama, kecuali Anda menambahkan pemartisian.

Pemartisian membagi data di beberapa instans basis data berdasarkan kunci partisi (misalnya, user_id mod N). Cara ini meningkatkan kapasitas penulisan, tetapi menghilangkan penggabungan dan transaksi lintas partisi — dua fitur terkuat SQL. Sebagian besar aplikasi web melampaui kemampuan SQL satu simpul ketika memiliki sekitar 5–10 TB data atau sekitar 100K penulisan/detik.

# 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')

Penyimpanan Kunci-Nilai: Redis dan DynamoDB

Penyimpanan kunci-nilai menyimpan data sebagai pasangan kunci → nilai dengan operasi baca dan tulis O(1) berdasarkan kunci. Penyimpanan ini mengorbankan fleksibilitas kueri demi performa ekstrem dan skalabilitas horizontal. Redis (dalam memori) mencapai latensi dalam hitungan mikrodetik; DynamoDB (terkelola) mencapai latensi dalam hitungan milidetik satu digit dengan penskalaan otomatis untuk throughput berapa pun.

Gunakan penyimpanan kunci-nilai untuk: penyimpanan sesi, penembolokan, tanda fitur, pemetaan URL ke tujuan, keranjang belanja, dan papan peringkat waktu nyata. Jangan gunakan ketika Anda memerlukan: kueri kompleks, hubungan antarentitas, atau penyaringan ad hoc — Anda hanya dapat melakukan pencarian berdasarkan kunci yang persis.

# 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')

Penyimpanan Dokumen: MongoDB

Penyimpanan dokumen (MongoDB, Couchbase) menyimpan data sebagai dokumen mirip JSON, sehingga memungkinkan skema fleksibel — bidang dapat berbeda antara dokumen dalam koleksi yang sama. Penyimpanan ini mendukung pengindeksan pada bidang apa pun dan kueri yang cukup kaya (penyaringan, proyeksi, agregasi), meskipun transaksi pada banyak dokumen lebih terbatas dibandingkan SQL.

Penyimpanan dokumen cocok untuk aplikasi yang: bentuk datanya berbeda-beda untuk setiap entitas (profil pengguna dengan atribut yang berbeda), mengharapkan perubahan skema yang cepat (perusahaan rintisan yang sering mengubah model data), atau pola pembacaannya lebih banyak mengambil entitas secara utuh daripada menggabungkan data lintas tabel.

# 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')

Penyimpanan Kolom Lebar: Cassandra

Penyimpanan kolom lebar (Apache Cassandra, HBase) menyimpan data dalam baris dan kolom, tetapi memungkinkan setiap baris memiliki kumpulan kolom yang berbeda. Penyimpanan ini dirancang untuk kapasitas penulisan masif yang didistribusikan di banyak simpul, dengan konsistensi pada akhirnya sebagai bawaan. Cassandra mencapai penskalaan penulisan linear — menggandakan jumlah simpul akan menggandakan kapasitas penulisan.

Komprominya: kueri harus dirancang berdasarkan kunci partisi. Anda tidak dapat menyaring atau mengurutkan kolom sembarang secara efisien — Anda harus menentukan pola kueri terlebih dahulu, lalu merancang tabel agar sesuai dengannya. Hal ini berlawanan dengan pendekatan SQL “rancang data, lalu tulis kueri apa pun”.

# 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)')

Teorema CAP: Konsistensi, Ketersediaan, Toleransi Partisi

Teorema CAP menyatakan bahwa sistem terdistribusi paling banyak dapat menjamin dua dari hal-hal berikut: Konsistensi (setiap pembacaan mengembalikan hasil penulisan terbaru), Ketersediaan (setiap permintaan mendapatkan respons yang bukan kesalahan), dan Toleransi partisi (sistem tetap beroperasi meskipun terjadi partisi jaringan).

Karena partisi jaringan selalu dapat terjadi dalam sistem terdistribusi, pilihan sebenarnya adalah antara CP (memprioritaskan konsistensi, dan mungkin menolak permintaan selama partisi) dan AP (memprioritaskan ketersediaan, dan mungkin mengembalikan data lama). Basis data SQL umumnya CP; Cassandra dan DynamoDB adalah AP (konsistensi pada akhirnya secara bawaan). Redis Cluster adalah 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"]}')

Memilih Penyimpanan: Kerangka Pengambilan Keputusan

Kerangka praktis untuk memilih penyimpanan dalam wawancara:

  • Memerlukan transaksi ACID? → Basis data relasional (PostgreSQL, MySQL)
  • Memerlukan pencarian dalam waktu kurang dari satu milidetik atau penembolokan? → Penyimpanan kunci-nilai (Redis)
  • Memerlukan skema fleksibel atau data berorientasi dokumen? → Penyimpanan dokumen (MongoDB)
  • Memerlukan kapasitas penulisan masif (>100K/detik) dengan data deret waktu atau peristiwa? → Penyimpanan kolom lebar (Cassandra)
  • Memerlukan distribusi global dengan penskalaan terkelola? → DynamoDB atau Cosmos DB
  • Memerlukan penelusuran graf? → Basis data graf (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)}')

Persistensi Poliglot: Menggunakan Beberapa Penyimpanan

Sistem produksi jarang menggunakan satu basis data untuk segala kebutuhan. Persistensi poliglot berarti menggunakan teknologi penyimpanan yang tepat untuk setiap bagian sistem. Aplikasi web pada umumnya mungkin menggunakan: PostgreSQL untuk data pengguna dan pesanan utama yang menjadi acuan, Redis untuk penyimpanan sesi dan penembolokan, Elasticsearch untuk pencarian teks lengkap, S3 untuk penyimpanan berkas, serta Cassandra untuk catatan peristiwa dan analitik.

Komprominya: kompleksitas operasional meningkat setiap kali jenis basis data baru ditambahkan. Tim harus memelihara, memantau, dan mencadangkan beberapa sistem. Alasan desainnya: peningkatan performa dan skalabilitas karena setiap beban kerja dipasangkan dengan penyimpanan yang tepat lebih besar daripada biaya operasionalnya pada skala besar.

# 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')

Strategi Pengindeksan di Berbagai Jenis Penyimpanan

Semua sistem penyimpanan menggunakan indeks untuk mempercepat pembacaan, dengan konsekuensi penulisan yang lebih lambat dan kebutuhan penyimpanan tambahan. Memahami pengindeksan pada berbagai jenis penyimpanan sangat penting dalam desain sistem:

  • SQL: indeks B-tree pada kolom apa pun; indeks gabungan untuk kueri pada banyak kolom; indeks cakupan untuk menghindari pencarian tabel
  • MongoDB: indeks pada bidang apa pun; indeks gabungan; indeks TTL untuk kedaluwarsa otomatis
  • Cassandra: hanya kunci partisi dan kolom pengelompokan yang diindeks secara bawaan; indeks sekunder mahal
  • Redis: himpunan terurut sebagai indeks untuk kueri rentang; pengindeksan tradisional tidak diperlukan untuk kunci-nilai
# 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 dibandingkan NoSQL dalam Wawancara: Apa yang Harus Diucapkan

Ketika ditanya “SQL atau NoSQL?” dalam wawancara desain sistem, jangan pernah memberikan jawaban satu kata. Sebagai gantinya, ikuti struktur berikut:

  1. Sampaikan beban kerja: “Beban ini didominasi pembacaan dengan penyaringan kompleks, jadi…”
  2. Sampaikan persyaratannya: “Kita memerlukan konsistensi kuat untuk transaksi keuangan, jadi…”
  3. Sampaikan pilihannya: “Saya akan menggunakan PostgreSQL dengan replika baca”
  4. Sampaikan komprominya: “Komprominya adalah penskalaan penulisan horizontal memerlukan pemartisian, yang menambah kompleksitas”
  5. Sebutkan alternatif: “Jika penulisannya lebih tinggi, kita dapat mempertimbangkan 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')

Pemeriksaan Singkat

Uji pemahaman Anda tentang konsep Struktur Data & Algoritma — Persiapan Wawancara Pemrograman dari pelajaran ini.

Rangkuman Pelajaran

Dalam pelajaran ini Anda mempelajari: basis data SQL menyediakan transaksi ACID dan kueri kompleks, tetapi sulit meningkatkan skala penulisannya, sementara basis data NoSQL mengorbankan konsistensi atau fleksibilitas kueri demi skala dan ketersediaan ekstrem, teorema CAP memaksa sistem terdistribusi memilih antara konsistensi dan ketersediaan selama terjadi partisi jaringan, dan sistem produksi biasanya menggunakan persistensi poliglot — mencocokkan setiap beban kerja dengan mesin penyimpanan yang tepat. Selanjutnya, kita akan membahas lapisan penembolokan, CDN, dan penyeimbangan beban untuk meningkatkan skala sistem yang didominasi pembacaan.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Penyimpanan Data Skalabel: SQL vs NoSQL” gratis?

Ya — teks lengkap “Penyimpanan Data Skalabel: SQL vs NoSQL” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus DSA Interview Prep, upgrade ke CoddyKit PRO. Kursus DSA Interview Prep mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Penyimpanan Data Skalabel: SQL vs NoSQL”?

Pilih antara basis data relasional, penyimpanan key-value, basis data dokumen, dan penyimpanan kolom lebar berdasarkan pola akses, konsistensi, dan kebutuhan skala Kamu berlatih DSA Interview Prep dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai DSA Interview Prep?

Tidak diperlukan pengalaman sebelumnya. DSA Interview Prep di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Penyimpanan Data Skalabel: SQL vs NoSQL” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran DSA Interview Prep ini?

Ya. Setiap pelajaran DSA Interview Prep menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Kerangka Wawancara Desain Sistem
  2. Penyimpanan Data Skalabel: SQL vs NoSQL
  3. Caching, CDN, dan Penyeimbangan Beban
  4. Merancang Pembatas Laju dan Merancang Feed Twitter
← Kembali ke DSA Interview Prep