Databases & Data Modeling
SQL vs NoSQL
Comparing relational and non-relational databases and when to use each.
In short
Comparing relational and non-relational databases and when to use each.
Neither is universally "better" — the choice depends on the data and access patterns. SQL excels when relationships and strong consistency matter; NoSQL excels when you need flexible schemas and horizontal scale.
1. Learning Objectives
By the end of this lesson, you will be able to:
- Evaluate the fundamental structural and architectural differences between relational (SQL) and non-relational (NoSQL) database paradigms.
- Map complex business domains and query patterns to appropriate data models, choosing between normalized relational schemas and denormalized document/key-value models.
- Contrast ACID transaction guarantees with the BASE consistency model, understanding when strong consistency is mandatory versus when eventual consistency is acceptable.
- Formulate horizontal and vertical scaling strategies, explaining database concepts such as replication, sharding, partition keys, and write amplification.
- Apply the CAP and PACELC theorems to analyze system behavior under network partitions and normal operations, predicting latency and consistency trade-offs.
2. Prerequisites
To get the most out of this lesson, you should be familiar with the following concepts:
- Basic Database Operations: Writing simple SQL queries (SELECT, JOIN, INSERT, UPDATE).
- Data Structures: Familiarity with Hash Maps, Trees (specifically B-Trees and Binary Trees), and Graphs.
- Distributed Systems Basics: Understanding client-server models, networking latency, and the concept of replica nodes.
3. Why This Topic Matters
In system design, database selection is a critical decision. Unlike application logic, which is stateless and easy to refactor or redeploy, database state is stateful, heavy, and extremely difficult to migrate. Choosing the wrong storage engine early in a system's lifecycle can lead to catastrophic scalability bottlenecks, high operational costs, and eventual multi-month or multi-year migration projects that stall product development.
For instance, migrating a multi-terabyte database from PostgreSQL to Apache Cassandra or vice versa requires complex double-writing phases, validation scripts, and high risk of data inconsistency. Understanding the core strengths, limits, and internal mechanics of SQL and NoSQL databases allows system architects to select the right tool for the job based on query patterns, consistency requirements, and write-to-read ratios.
4. Real-world Analogy
Imagine organizing a large, physical records archive:
The SQL Approach (The Law Firm filing system): Think of a highly standardized filing cabinet where every folder has a strict template. There is one drawer for Clients, another drawer for Invoices, and a third for Case Records. Invoices cross-reference Client IDs. If you want to check an invoice, you fetch the client details from the client drawer and map them. Adding information requires matching the exact pre-defined forms. This ensures that records are always clean, complete, and perfectly cross-referenced. However, if the firm grows massive, you cannot easily split these drawers across separate buildings without hiring a courier to constantly run back and forth to maintain the cross-references.
The NoSQL Approach (The Shipping Warehouse storage boxes): Think of cardboard storage boxes stacked on pallets. Each box represents a customer order. Inside a single box, you put the client's profile sheet, their invoices, and list of ordered items. The contents don't have to follow a strict structure; one box might contain a handwritten note, while another contains a printout. If the warehouse runs out of space, you simply buy another warehouse next door and stack new boxes there (horizontal scaling). Finding a single box by its box ID is incredibly fast. However, if you want to run a report calculating the total sales of a specific product category across all boxes, you have to manually open and search every single box in both warehouses—a highly inefficient process compared to the law firm's index system.
5. Core Concepts
To compare these databases, we must first understand the core attributes of each model:
Relational Databases (SQL)
- Structured Schema: Data is organized into tables (relations) containing rows (tuples) and columns (attributes). The schema must be declared beforehand.
- Normalization: The practice of structuring data to reduce redundancy and maintain integrity (e.g., separating tables and using foreign keys).
- ACID Transactions: Guaranteeing Atomicity (all-or-nothing), Consistency (moves from one valid state to another), Isolation (concurrent transactions don't interfere), and Durability (committed changes persist).
Non-Relational Databases (NoSQL)
NoSQL refers to "Not Only SQL" and represents databases designed for unstructured, semi-structured, or highly polymorphic data models. They are categorized by data representation:
- Key-Value Stores: Data is stored as an arbitrary collection of bytes (value) indexed by a unique string (key). Highly optimized for fast, single-key lookups. (Examples: Redis, Riak).
- Document Stores: Data is stored as hierarchical documents (JSON, BSON, XML). Documents are self-describing and can have variable schemas. (Examples: MongoDB, CouchDB).
- Wide-Column (Column-Family) Stores: Data is stored in rows containing dynamic columns. Under the hood, data is organized column-by-column rather than row-by-row, facilitating horizontal partitioning and high write throughput. (Examples: Apache Cassandra, ScyllaDB, HBase).
- Graph Databases: Data is represented as nodes (entities) and edges (relationships) with properties. Optimized for traversing deep networks of relationships. (Examples: Neo4j, Amazon Neptune).
Consistency Paradigms
While SQL relies on ACID, NoSQL databases typically adopt the BASE model to achieve high scale and availability:
- Basically Available: The system remains operational during failures, though some partitions may be unreachable or degraded.
- Soft State: The data state can drift over time without developer intervention due to lack of immediate consistency guarantees.
- Eventual Consistency: The system will eventually become consistent across all replica nodes if no new updates are made.
6. Visualization
The diagram below demonstrates how data scaling differs structurally between SQL (typically Master-Replica or Sharded vertical pipelines) and NoSQL (typically partition-based peer-to-peer rings):
7. How It Works
Let's walk through the low-level lifecycle of data mutations and retrievals for both relational databases and non-relational databases.
Relational Database (SQL) Mutation Lifecycle
- Connection & Parsing: The client sends an
INSERTorUPDATEquery over TCP. The database server parses the query to verify syntactical correctness. - Query Optimizer: The query planner evaluates potential access paths (e.g., index scans vs. table scans) and chooses the cheapest execution plan.
- Locking & Concurrency Control: The Lock Manager acquires the necessary locks (row-level, page-level, or table-level) based on the transaction's isolation level to prevent concurrency anomalies.
- Buffer Pool Check: The engine checks if the target data page resides in the in-memory Buffer Pool. If not, it reads the page from disk into memory.
- Write-Ahead Log (WAL): The mutation is written sequentially to the Write-Ahead Log (WAL) on disk. This is a critical step for durability; the update is only considered committed once it is flushed to the WAL.
- In-Memory Modification: The page in the buffer pool is updated (marked as "dirty"). An asynchronous background process (cleaner thread) will write this dirty page back to the main database file on disk.
- Acknowledgment: The transaction is declared successful, locks are released, and the client receives a success status code.
Non-Relational Database (NoSQL - Wide-Column/LSM-Tree) Write Lifecycle
- Routing: The client sends a write request with a specific Partition Key. The client driver or a router node hashes the key to locate the target node(s) on the consistent hashing ring.
- Commit Log Write: The target replica node receives the write and immediately writes it to an append-only Commit Log on disk to guarantee durability.
- Memtable Write: The write is then recorded in an in-memory data structure called a Memtable (often implemented as a red-black tree or skip list). At this point, the write is complete from the client's perspective and acknowledged.
- SSTable Flush: When the Memtable fills up to its threshold, it is flushed to disk as an immutable Sorted String Table (SSTable). Since it is immutable, there are no disk seek-and-rewrite overheads.
- Compaction: In the background, a compaction thread merges overlapping SSTables, removing deleted items (marked with "tombstones") and keeping only the latest version of duplicate keys.
8. Internal Architecture
To understand why SQL and NoSQL behave differently, we must look at their internal component organization. The table below lists these systems' respective architectures:
| Component | SQL (RDBMS Engine) | NoSQL (Distributed Wide-Column/Doc) | Primary Failure Points |
|---|---|---|---|
| Storage Layout | B+ Tree (highly optimized for read indexing, random write seeks). | LSM-Tree / Memtable + SSTable (optimized for append-only sequential writes). | B+ Tree page fragmentation; LSM-Tree write/read amplification. |
| Query Planning | Cost-Based Optimizer (analyzes table statistics, plans joins, subqueries). | Simple Query Router (evaluates hash key, routes directly to target node). | SQL: stale statistics leading to bad query plans; NoSQL: routing bottleneck if coordinator is overloaded. |
| Replication Control | Master-Replica (Active-Passive or semi-synchronous replication). | Multi-Master / Leaderless ring topology (Gossip protocol, hinted handoffs). | RDBMS: Master node failure during failover (split-brain). NoSQL: Network split leading to divergence. |
| Locking Engine | Lock Manager (tracks page, row, and table locks; detects deadlocks). | Lock-free (mostly optimistic locking, row versioning, or last-write-wins). | SQL: Lock contention, deadlock aborts. NoSQL: Silent data loss via Last-Write-Wins (LWW) clock drift. |
9. Request Lifecycle
Let's visual-track the execution flow of specific requests under normal operations.
Case A: SQL Transaction (Transferring money between two accounts)
- The client sends
BEGIN TRANSACTION. - The client issues:
UPDATE accounts SET balance = balance - 100 WHERE id = 1;. The database obtains a write lock on Row 1, updates the buffer page, and logs it to WAL memory. - The client issues:
UPDATE accounts SET balance = balance + 100 WHERE id = 2;. The database obtains a write lock on Row 2, updates the buffer page, and logs it. - The client issues
COMMIT. - The engine forces the WAL pages containing these operations to be flushed to non-volatile storage (disk sync).
- Once the WAL is successfully synced, the database releases all locks on Rows 1 & 2, and responds with a transaction commit success.
Case B: NoSQL Eventual Consistency Write (Posting a status update to a profile)
- The client submits a write request with partition key
user_id = 9876to any node in the cluster (acting as the Coordinator). - The Coordinator uses consistent hashing to determine the primary nodes responsible for the partition key (e.g., Nodes A, B, and C).
- The Coordinator forwards the write to Nodes A, B, and C.
- Assuming a quorum write setting (W=2, N=3), the Coordinator waits for at least two nodes to acknowledge the write.
- Node A and Node B write the data to their memtables and commit logs, then reply with success. Node C is experiencing temporary network latency and does not respond immediately.
- The Coordinator receives the two acknowledgments (meeting W=2) and returns a success response to the client application.
- Eventual Resolution: Later, Node C recovers, and either a background read-repair (triggered when a client reads from C and A/B concurrently) or a hinted handoff (where Node A delivers the stored missed update to C) restores C's data consistency.
10. Deep Dive
B+ Trees vs. LSM Trees
The architectural divergence between SQL and NoSQL databases is heavily dictated by their chosen index structure:
- B+ Trees (Common in RDBMS): Organized in a tree structure where leaf nodes contain pointers to data pages, and all leaves are linked together in a sequence. Read queries are extremely fast (O(log N)) and predictable because finding a key requires traversing a fixed depth. However, writing requires modifying existing pages in place. If the page is not in memory, this causes random disk I/O, leading to write latency degradation as the database size outgrows the RAM.
- LSM Trees (Common in Wide-Column/Key-Value NoSQL): Designed to avoid random I/O. All writes are recorded in sequence in a Memtable (memory) and immediately appended to a commit log. Memtables are periodically flushed to disk as immutable, sorted SSTables. This turns random write queries into high-throughput sequential disk writes. However, read operations are more expensive (O(K log N), where K is the number of SSTables) because the system may need to search multiple files on disk to find the most recent state. To mitigate this, LSM engines use Bloom Filters (highly space-efficient probabilistic data structures) to check if a key exists in an SSTable before performing disk seeks.
Distributed Consensus vs. Peer-to-Peer
Distributed SQL (e.g., Google Spanner, CockroachDB) uses Paxos or Raft consensus algorithms to coordinate multi-node changes. This maintains strong transactional integrity across physical regions but introduces a latency cost: every write transaction requires a round-trip consensus among a majority of replica nodes.
In contrast, Dynamo-style NoSQL engines use a masterless structure where nodes gossip to monitor node health and route requests. Instead of strict locks, they resolve write conflicts using Last-Write-Wins (LWW), which uses system clocks to decide which value is correct, or vector clocks. Clock drift between servers is a notorious source of silent data corruption in such databases.
The PACELC Theorem
While the CAP Theorem states that a system can only guarantee two out of Consistency, Availability, and Partition Tolerance, the PACELC theorem expands on this to describe behavior during normal operations (non-partition states):
If there is a Partition (P), how does the system choose between Availability (A) and Consistency (C)? Else (E), how does it choose between Latency (L) and Consistency (C)?
- MongoDB: Classified as PC/EC. During partitions, it rejects writes to maintain consistency (PC). During normal operations, it prioritizes consistency (EC) by routing reads/writes to the primary node.
- Apache Cassandra: Classified as PA/EL. During partitions, it accepts writes on any node (PA). During normal operations, it prioritizes latency (EL) by serving reads from nearby replicas without coordinating a global consensus.
11. Production Example
Netflix: Viewing History (Cassandra)
Netflix has hundreds of millions of active profiles, each continuously generating viewing telemetry (e.g., pause, play, progress updates). The database must handle massive, continuous write volumes globally with sub-millisecond response times. Netflix utilizes Apache Cassandra (NoSQL Wide-Column) to solve this. Because viewing history does not require multi-row transactions, Cassandra partitions data by profile_id, allowing it to scale linearly by adding nodes. Eventual consistency is perfectly fine: if a user stops watching a movie on their TV and immediately checks their phone, it is acceptable if the progress bar takes 2 seconds to sync.
Uber: The Evolution from PostgreSQL to Schemaless
Uber originally started with a single monolithic PostgreSQL database. As trip volumes surged, PostgreSQL struggled with write volumes due to Write Amplification. In Postgres, changing a row requires updating all indexes (indexes point directly to the physical row ID). When Uber updated driver coordinates every few seconds, this triggered massive index write loads. Uber ultimately migrated to "Schemaless," a custom document-like database layered on top of MySQL sharded instances. By using MySQL InnoDB (which stores index lookups pointing to a primary key instead of physical row offsets) and adopting an append-only NoSQL-like pattern, Uber mitigated write amplification and scaled its trip data tier horizontally.
12. Advantages
SQL Databases
- Strong Schema Enforcement: Prevents corrupted or invalid data entries at the database layer.
- Powerful Join Queries: Complex relationships can be queried on the fly using standard declarative SQL, reducing application logic.
- ACID Guarantees: Essential for operations requiring mathematical precision and high integrity (e.g., ledger balances, order checkouts).
- Mature Tooling: Decades of optimization, rich ecosystems, standardized drivers, and vast community knowledge.
NoSQL Databases
- Elastic Scaling: Nodes can be added horizontally without complex re-architecting, distributing data across partitions seamlessly.
- High Write Throughput: LSM-based engines handle high-frequency writes (logs, metrics, chat messages) with minimal disk seek delays.
- Dynamic/Flexible Schemas: Allows storing nested objects with differing attributes, allowing rapid application development without schema migration overhead.
- High Availability: Multi-master rings and localized quorum reads ensure the database remains operational even when multiple servers drop offline.
13. Limitations
SQL Databases
- Vertical Scale Limits: Eventually, a single master server will hit hardware ceilings (CPU cores, NVMe IOPS limits).
- High Sharding Complexity: Sharding an RDBMS requires custom application routing logic, managing distributed transactions, or relying on heavy middleware (e.g., Vitess).
- Rigid Schemas: Executing an
ALTER TABLEon a production table containing hundreds of millions of rows can lock tables, causing service downtime.
NoSQL Databases
- No Native Joins: Joining data requires manual client-side queries or expensive map-reduce jobs.
- Lack of Global Consistency: Eventual consistency can lead to confusing application race conditions if not managed properly.
- Query Limits: Access is optimized around the chosen partition keys. Querying by other columns requires full-table scans or secondary indexes, which degrade scale.
14. Trade-offs
When choosing between SQL and NoSQL, architects trade off three key properties:
- Normalization vs. Denormalization: SQL normalizes data to minimize storage footprint and guarantee a single source of truth. However, reading this data requires assembling pages using CPU-intensive JOINs. NoSQL denormalizes data by embedding related items. This duplicates storage space but allows retrieving a complete object in a single read request.
- Consistency vs. Latency (PACELC): Under normal operations, NoSQL systems choose Latency over Consistency (EL), while SQL databases choose Consistency (EC). If your domain requires that a user immediately see their updated profile photo, SQL is safer; if you prefer page speed, eventual consistency NoSQL is superior.
- System Agility vs. Data Reliability: A strict schema (SQL) slows down early-stage features because engineers must continuously run schema migrations. However, a flexible schema (NoSQL) moves the responsibility of validation to the application. If data structures drift over months of product development, the application code becomes cluttered with backward-compatibility checks.
15. Performance Considerations
Database performance is highly dependent on access patterns and hardware characteristics:
- Write Amplification: Relational databases write data in pages (typically 8KB or 16KB). When a single row is modified, the entire page must be written back to disk, along with updating all index branches. Under heavy write loads, this causes high write amplification. LSM-Trees append data in memory and write sequential blocks to disk, which has lower write amplification but higher read latency over time.
- Connection Management: Traditional RDBMS engines allocate a process or a thread per client connection (e.g., PostgreSQL). This makes connection state heavy. NoSQL databases (like DynamoDB or MongoDB) are designed to handle stateless connections over HTTP/REST or optimized Multiplexed TCP connections, scaling to tens of thousands of concurrent connections.
- Bloom Filters: In LSM-Tree based NoSQL systems, checking if a key exists requires looking through multiple SSTables. To avoid excessive disk reads, the engine uses Bloom filters stored in RAM. Tuning the false-positive rate of Bloom filters is a common way to improve NoSQL read performance.
16. Failure Scenarios
1. The Hot Partition Issue (NoSQL Partition Imbalance)
In NoSQL systems, data is routed to nodes by hashing a partition key. If the key has low cardinality (e.g., partitioning by country or tenant_id), one popular value (like a large enterprise tenant) will receive 90% of the traffic. The single node holding that partition key will experience high CPU usage and disk I/O, leading to latency spikes, while other nodes in the cluster remain idle.
2. Split-Brain in RDBMS Failover
If a network partition isolates the RDBMS Master node from its replicas, the replication controller might assume the master is dead and promote a replica to master. If the old master is still running and accessible to a subset of clients, two nodes will accept write traffic simultaneously. Once the network partition heals, resolving conflicting writes is extremely difficult, often requiring manual database repair or resulting in data loss.
3. Index Bloat and Sequential Scan Failures in SQL
In SQL databases, deleting or updating rows does not immediately reclaim disk space; it marks pages as empty. Over time, indexes and tables become fragmented (bloated). If queries bypass indexes (e.g., using wildcard searches like LIKE '%john%'), the database must scan the entire tablespace. This blocks the buffer pool, displacing active pages and slowing down all other transactions in the system.
17. Best Practices
When Designing with SQL
- Keep Transactions Short: Lock rows only for as long as necessary to minimize deadlock risk and lock queues.
- Use Connection Poolers: Use lightweight connection proxies (e.g., PgBouncer for PostgreSQL) to manage connection limits and reuse TCP states.
- Define Proper Indexes: Always index foreign keys and columns that frequently appear in
WHEREclauses, but avoid over-indexing to keep write operations fast. - Normalize Wisely: Normalize to 3NF for transactional tables, but don't hesitate to selectively denormalize tables when read joins become performance bottlenecks.
When Designing with NoSQL
- Model Around Query Patterns: Unlike SQL, you must design NoSQL tables knowing exactly what queries your application will run (access-pattern-first design).
- High-Cardinality Keys: Ensure partition keys have wide ranges of unique values (e.g.,
user_idoruuidcombined with a timestamp) to prevent hot partitions. - Enforce Schema Integrity in Application: Build strong schema validation rules using libraries (e.g., Zod, Pydantic, or Mongoose) to prevent database pollution.
- Set TTLs (Time-To-Live): Leverage built-in TTL features for high-frequency logs, sessions, or temporary data to automatically clean up disk space.
18. Common Mistakes
- Choosing NoSQL by Default for Hype: Many developers choose NoSQL because it is perceived as modern or highly scalable, only to spend months writing application-side joins and manual validations that standard SQL engines handle natively.
- Treating Document Stores like Relational Databases: Designing a Document database schema with references (simulating foreign keys) instead of embedding documents, which leads to slow application-side round-trip queries.
- Using Multi-Row Transactions in Eventual-Consistency Stores: Attempting to build ledger/financial software on top of NoSQL databases without distributed transaction layers, leading to race conditions and account balance drifts.
- Allowing Unlimited Document Growth: In MongoDB, document sizes are capped (e.g., 16MB). Storing arrays that grow indefinitely (e.g., a list of a user's page views) will eventually hit the limit, crashing writes for that user.
19. Implementation
The following Python script illustrates how data modeling and query operations differ between a relational database (normalized SQL database using SQLite) and a non-relational database (denormalized Document/NoSQL database represented using memory-based dictionaries):
20. Interview Questions
Easy: Explain the difference between ACID and BASE properties.
Answer:
ACID stands for Atomicity, Consistency, Isolation, and Durability. It is typical of relational (SQL) databases and focuses on immediate data integrity. In ACID, a transaction is an all-or-nothing operation, and once committed, data is immediately consistent across all read paths.
BASE stands for Basically Available, Soft State, and Eventual Consistency. It is typical of non-relational (NoSQL) databases and prioritizes availability and performance over immediate consistency. In BASE, the database state can drift over time (Soft State), but once replica updates propagate, the database eventually converges to a consistent state (Eventual Consistency).
Medium: How would you shard a relational database, and what challenges does it introduce?
Answer:
Sharding is the process of partitioning your database rows horizontally across separate database instances (shards) based on a shard key (e.g., hashing user_id). For instance, users with ID 1-1000000 reside on Shard A, while 1000001-2000000 reside on Shard B.
The primary challenges sharding introduces include:
- Cross-Shard Joins: Joining data across shards is extremely expensive and must be handled in the application layer.
- Distributed Transactions: ACID transactions spanning multiple shards require Two-Phase Commit (2PC) protocols, which introduce significant latency and synchronization overhead.
- Resharding: If one shard fills up or becomes hot, redistributing the shard keys across new physical instances without system downtime requires complex migration pipelines.
Hard: How do you design a database architecture for a global multiplayer game leaderboard with millions of active users? Compare an RDBMS with sharding vs. a Wide-Column store like Cassandra.
Answer:
A global leaderboard requires high-throughput writes (updating player scores) and fast query reads (retrieving the top 100 players or a player's rank).
Using an RDBMS (e.g., PostgreSQL sharded by region):
- Write Path: Moderately complex. Score updates require locating the player's regional shard and updating their row. B+ Tree updates cause random writes on disk.
- Read Path: Fast for regional queries, but building a global leaderboard requires querying every single shard and aggregating/sorting the results in application memory, which scales poorly.
- Pros/Cons: Strong ACID consistency ensures scores are never corrupted, but horizontal scaling for global reads is a massive bottleneck.
Using Cassandra (NoSQL Wide-Column):
- Write Path: Highly optimized. LSM-Trees append score updates sequentially. Cassandra's consistent hashing distributes the write load evenly across nodes.
- Read Path: Data can be partitioned by game tournament/week, with player scores stored as clustering columns sorted in descending order. Finding the top 100 players is a single, pre-sorted partition read.
- Pros/Cons: Excellent scaling and write capacity. However, eventual consistency means player ranks may update slightly out-of-order on different clients, which is usually acceptable for gaming leaderboards.
21. Practice Exercises
Easy
Model a simple blogging platform database schema. Design a normalized version for SQL (representing users, posts, comments, tags) and an embedded, denormalized JSON document representation for NoSQL.
Medium
You run a production service on a single PostgreSQL instance. The table storing web sessions is reaching 5TB, causing RAM pressure. Outline a step-by-step strategy to migrate this session store to Redis or DynamoDB with zero downtime for active users.
Hard
Design a conflict resolution algorithm for a distributed, multi-region NoSQL document store that does not use system clocks (to avoid clock drift issues). Describe how you would implement Vector Clocks or CRDTs (Conflict-Free Replicated Data Types) to resolve overlapping writes on the same document partition.
22. Challenge Problem
Scenario: You are the lead database architect at a global ride-hailing company (like Uber). You are designing the storage backend for two primary data flows:
- Real-time Vehicle Tracking: Every driver’s app ping sends updated GPS coordinates (latitude, longitude) every 3 seconds to the server. Latency must be extremely low (<50ms), and availability is critical. Stale telemetry from 10 minutes ago is useless.
- Ride Receipts & Billing: Once a trip completes, the system calculates the final price, charges the customer, drafts a receipt, and records taxes. This data must never be lost, must support strict transactional integrity (cannot charge twice, must match rider and driver ledgers exactly), and must support complex financial audits.
Your Task: Propose a hybrid database architecture (Polyglot Persistence) that solves both flows. Clearly detail which database technologies you would use for each flow (SQL vs. specific NoSQL types), how they write/read, and how they interact to maintain a seamless user experience.
23. Summary
Here are the essential takeaways from this comparison:
- No Universal Solution: The database choice is not about selecting the "most modern" tech; it is about matching your access pattern.
- SQL Strengths: Structured data, strict schema enforcement, complex relations, and strong ACID transactional guarantees. Scale is achieved vertically or via specialized sharding.
- NoSQL Strengths: Scale-out capabilities, write optimization (using LSM-Trees/SSTables), flexible data models, and high availability using eventually consistent partitions.
- Polyglot Persistence: High-scale modern systems rarely use a single database. They use SQL for transactions and core accounting, Redis for cache/sessions, and Wide-Column databases for analytics, chats, or tracking logs.
24. Cheat Sheet
| Parameter | SQL (Relational) | NoSQL (Non-Relational) |
|---|---|---|
| Scaling | Vertical (scale up). Horizontal sharding requires manual app complexity. | Horizontal (scale out). Data is partitioned across node clusters automatically. |
| Schema | Fixed. Declared and migrated beforehand. Strong validation. | Dynamic. Can vary per document/row. Flexible and polymorphous. |
| Joins | Declarative, powerful JOIN operations supported out-of-the-box. |
None or highly limited. Requires denormalization or client-side aggregation. |
| Data Structure | B+ Trees (Optimized for reads and range queries). | LSM-Trees/SSTables (Write-friendly) or key-value structures. |
| Consistency | Strong consistency (ACID). Focuses on correctness. | Eventual consistency (BASE). Focuses on availability and speed. |
| Ideal Use Cases | Financial ledgers, relational ERPs, inventory management. | Social media feeds, IoT telemetry, real-time chats, caching. |
25. Quiz
-
Which structure is most commonly optimized for append-only, high-write NoSQL systems?
- A) Red-Black Trees
- B) B+ Trees
- C) LSM-Trees (Log-Structured Merge-Trees)
- D) AVL Trees
Answer: C. LSM-Trees write sequentially to disk, making them highly efficient for heavy write workloads compared to B+ Trees.
-
What is the primary trade-off highlighted by the PACELC theorem for a NoSQL system like Cassandra under normal operations?
- A) Availability vs. Consistency
- B) Latency vs. Consistency
- C) Durability vs. Latency
- D) Security vs. Throughput
Answer: B. PACELC states that "Else" (when no partition exists), a system must trade off Latency (L) against Consistency (C). Cassandra chooses low latency over immediate consistency.
-
Which normalization level focuses on eliminating transitive dependencies?
- A) First Normal Form (1NF)
- B) Second Normal Form (2NF)
- C) Third Normal Form (3NF)
- D) Boyce-Codd Normal Form (BCNF)
Answer: C. Third Normal Form requires that all non-key columns depend only on the primary key, removing transitive dependencies.
-
In a distributed Cassandra cluster, what is the role of the Gossip Protocol?
- A) Writing data to SSTables
- B) Executing SQL-to-CQL conversion
- C) Sharing cluster state, node status, and token ranges among peers
- D) Coordinating distributed transactions via two-phase commit
Answer: C. Gossip protocol is used in peer-to-peer databases to periodically exchange state information without a centralized leader.
-
What does a Bloom Filter do in a Document or Wide-Column store?
- A) Compresses documents to save disk space
- B) Guarantees that a key is present on disk with 100% accuracy
- C) Quickly determines if a key is definitely NOT in an SSTable, preventing unnecessary disk seeks
- D) Resolves write-write conflicts between different replica nodes
Answer: C. Bloom filters are probabilistic structures that return a definitive negative or a tentative positive, avoiding expensive random disk reads.
-
Which failure scenario occurs when a network split causes two nodes in an RDBMS cluster to claim they are the active master?
- A) Hot Partitioning
- B) Write Amplification
- C) Split-Brain
- D) Cascading Failure
Answer: C. Split-brain happens when communication breaks down and two servers independently take over master duties.
-
Why did Uber migrate away from PostgreSQL to a MySQL-based schemaless architecture?
- A) MySQL supported standard SQL transactions while Postgres did not
- B) Postgres suffered from index write amplification because updates required rewriting physical row offsets in all indexes
- C) PostgreSQL lacks B+ Tree index structures
- D) MySQL supported native graph database queries out-of-the-box
Answer: B. In Postgres, physical row updates require updating all secondary indexes, leading to massive write amplification under telemetry-heavy write workloads.
-
What happens when a NoSQL document database exceeds its maximum document size (e.g., 16MB in MongoDB)?
- A) The document is automatically split into a new collection
- B) The database engine compresses the document dynamically
- C) The write operation fails with an error
- D) The database switches to column-store mode
Answer: C. Storing unbounded arrays (like infinite message logs) in a single document will hit database limits and trigger write failures.
-
If a business requires a high rate of ad-hoc queries spanning multiple tables and relations that change over time, which model is best suited?
- A) Wide-Column (Cassandra)
- B) Key-Value Store (Redis)
- C) Relational (SQL)
- D) Graph Database (Neo4j)
Answer: C. SQL's query optimizer and relational JOIN support make it ideal for ad-hoc, multi-dimensional queries.
-
What is a Hinted Handoff in NoSQL database engines?
- A) Passing write validation from server to client
- B) Storing a write update locally on a coordinator for a temporarily offline node, and delivering it when the node recovers
- C) Sharding a hot partition to a neighboring node
- D) Performing a database backup while processing writes
Answer: B. Hinted handoffs assist in high-availability environments by storing missed updates until peer nodes recover.
26. Further Reading
- The Dynamo Paper (Amazon): Dynamo: Amazon’s Highly Available Key-value Store - The seminal paper on decentralized NoSQL.
- The Spanner Paper (Google): Spanner: Google’s Globally-Distributed Database - Explaining how TrueTime atomic clocks achieve external consistency.
- Designing Data-Intensive Applications (Book): Martin Kleppmann - Chapters 3 (Storage and Retrieval) and 5 (Replication) provide the best low-level breakdown of these concepts.
27. Next Lesson Preview
In the next lesson, we will dive deeper into one of the key scaling methods for relational systems: Database Sharding and Partitioning. We will look at horizontal sharding algorithms, range-based vs. directory-based routing, and how to manage global shard indexes with zero downtime.
Key takeaways
- Match the database to the access pattern, not hype.
- Polyglot persistence — use the right store for each job.