blog.dopana

Back

Chọn database là một trong những quyết định quan trọng nhất khi thiết kế hệ thống. SQL hay NoSQL? Câu trả lời: “tùy”.

SQL — Structured Query Language#

Ví dụ: PostgreSQL, MySQL, SQLite, MariaDB, SQL Server

Đặc điểm#

  • Schema cố định — bảng, cột, kiểu dữ liệu định nghĩa trước
  • ACID — Atomicity, Consistency, Isolation, Durability
  • Relations — JOIN giữa các bảng qua foreign key
  • Mature — 50+ năm phát triển, tooling phong phú

Khi nào dùng SQL#

-- Dữ liệu có quan hệ rõ ràng
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INT REFERENCES users(id),
    total DECIMAL(10,2),
    created_at TIMESTAMP DEFAULT NOW()
);

-- Cần JOIN, transaction, consistency
SELECT u.name, COUNT(o.id) as order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id
HAVING COUNT(o.id) > 5;
sql

Use case: Finance, ERP, CRM, hệ thống cần consistency mạnh.

NoSQL — Not Only SQL#

Ví dụ: MongoDB (Document), Redis (Key-Value), Cassandra (Wide-column), Neo4j (Graph)

Document DB (MongoDB)#

// Schema-less — mỗi document có thể khác nhau
{
  "_id": "user_123",
  "name": "Alice",
  "email": "alice@example.com",
  "orders": [
    { "id": "ord_1", "total": 100, "items": ["item_a", "item_b"] },
    { "id": "ord_2", "total": 50 }
  ]
}
json

Ưu: Linh hoạt, không cần migration, dữ liệu lồng nhau tự nhiên. Nhược: Không JOIN, không ACID mạnh (MongoDB có transaction nhưng limited).

Key-Value (Redis)#

SET user:123 '{"name":"Alice","email":"alice@example.com"}'
SET session:abc123 user_123 EX 3600
LPUSH notifications:user_123 "New message"
bash

Ưu: Siêu nhanh (in-memory), đơn giản. Nhược: Không query phức tạp, dữ liệu phải fit memory.

Wide-column (Cassandra)#

CREATE TABLE user_events (
    user_id UUID,
    event_time TIMESTAMP,
    event_type TEXT,
    data TEXT,
    PRIMARY KEY (user_id, event_time)
);
sql

Ưu: Scale ngang cực tốt, write throughput cao. Nhược: Query pattern phải biết trước, không JOIN.

Graph (Neo4j)#

MATCH (u:User {id: '123'})-[:FOLLOWS]->(f:User)-[:POSTED]->(p:Post)
RETURN p
cypher

Ưu: Quan hệ phức tạp, recommendation, social graph. Nhược: Không tốt cho simple CRUD.

So Sánh#

Tiêu chíSQLNoSQL
SchemaCố định, rigidLinh hoạt, dynamic
ACIDMạnh (full ACID)Yếu hơn (tùy loại)
JOINTốt, built-inKhông hoặc limited
ScaleVertical (chính)Horizontal (dễ)
QuerySQL chuẩn, mạnhTùy database
ConsistencyStrongEventual (thường)
MaturityCaoTrung bình

CAP Cho Database#

SQL (PostgreSQL):  CP — ưu tiên Consistency
MongoDB:          CP (mặc định) hoặc AP
Cassandra:        AP — ưu tiên Availability
Redis:            CP (single node) hoặc AP (cluster)
plaintext

Khi Nào Chọn SQL#

  • Dữ liệu có quan hệ chặt chẽ (user-order-product)
  • Cần transaction (chuyển tiền, đặt hàng)
  • Query phức tạp, nhiều JOIN
  • Schema ổn định, ít thay đổi
  • Consistency là ưu tiên hàng đầu

Khi Nào Chọn NoSQL#

  • Schema thay đổi thường xuyên (MVP, poc)
  • Cần scale ngang lớn (millions của users)
  • Dữ liệu nested tự nhiên (JSON, document)
  • Cache, session, real-time (Redis)
  • Time-series data, event logging (Cassandra, InfluxDB)
  • Social graph, recommendation (Neo4j)

Polyglot Persistence — Dùng Cả Hai#

Nhiều hệ thống dùng nhiều database cho nhiều mục đích:

PostgreSQL → Dữ liệu chính (orders, users, products)
Redis      → Cache, session, rate limiting
MongoDB    → Content, bài viết, log
Elasticsearch → Full-text search
plaintext

Không có luật nào cấm dùng cả SQL và NoSQL trong cùng project.

Migration từ SQL sang NoSQL#

Kết Luận#

SQL không chết, NoSQL không phải thần dược. Chọn theo:

  1. Dữ liệu có quan hệ? → SQL
  2. Cần ACID? → SQL
  3. Cần scale ngang? → NoSQL
  4. Schema thay đổi liên tục? → NoSQL
  5. Phân tích real-time? → NoSQL (Cassandra, ClickHouse)

Hay nhất: biết cả hai. Dự án thực tế thường dùng PostgreSQL + Redis.

Tài liệu tham khảo#