1. Database là gì?
Database (CSDL) là một tập hợp dữ liệu có tổ chức, được quản lý bởi một
DBMS (Database Management System) để hỗ trợ truy vấn, cập nhật, đảm bảo tính nhất quán
và bền vững. Khác với file phẳng (.csv, .json), DB cho bạn:
- Truy vấn theo cấu trúc — hỏi "User nào có trên 100 đơn hàng tháng 5?" mà không phải đọc toàn bộ file.
- Concurrent access — nhiều client cùng đọc/ghi an toàn (transactions, locks, MVCC).
- Đảm bảo nhất quán — qua constraints (FK, UNIQUE, CHECK), schema, ACID.
- Khôi phục sau crash — Write-Ahead Log (WAL), backup, replication.
- Hiệu năng — Index làm tra cứu O(log n) thay vì O(n) full scan.
Quy tắc ngón tay cái
Khi dữ liệu vượt quá vài MB, có nhiều người cùng truy cập, hoặc bạn cần truy vấn linh hoạt — hãy dùng DB.
File .json/.csv chỉ phù hợp cho cấu hình tĩnh hoặc dữ liệu nhỏ chỉ-đọc.
2. Các loại Database
┌────────────────────── DATABASE ECOSYSTEM ──────────────────────┐
│ │
│ ┌─ RELATIONAL (SQL) ──────────────────┐ │
│ │ PostgreSQL · MySQL · SQLite │ ← OLTP, ACID, JOINs │
│ │ SQL Server · Oracle · MariaDB │ │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─ NOSQL ─────────────────────────────────────┐ │
│ │ Key-Value: Redis · DynamoDB · Memcached │ ← cache, session │
│ │ Document: MongoDB · Couchbase │ ← flexible JSON │
│ │ Wide-column: Cassandra · ScyllaDB · HBase │ ← write-heavy │
│ │ Graph: Neo4j · Neptune · Dgraph │ ← relationships │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌─ ANALYTICAL (OLAP) ─────────────────┐ │
│ │ Snowflake · BigQuery · Redshift │ ← BI, warehouse, columnar │
│ │ ClickHouse · DuckDB │ │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─ SEARCH / VECTOR ───────────────────┐ │
│ │ Elasticsearch · OpenSearch │ ← full-text search │
│ │ Pinecone · Weaviate · pgvector │ ← AI embeddings │
│ └─────────────────────────────────────┘ │
│ │
│ ┌─ TIME-SERIES ───────────────────────┐ │
│ │ InfluxDB · TimescaleDB · Prometheus│ ← metrics, IoT │
│ └─────────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
Trong khóa học này, ta sẽ tập trung vào 3 nhóm chính: Relational SQL (Ch1–8), NoSQL (Ch9), và các
pattern phụ trợ Caching/Search/OLAP (Ch11). Time-series và Vector DB được nhắc đến ngắn gọn nhưng không đào sâu.
3. Mô hình quan hệ — vì sao SQL thống trị 50 năm?
Năm 1970, Edgar F. Codd publish bài báo nổi tiếng "A Relational Model of Data for Large Shared Data Banks"
đặt nền móng cho mô hình quan hệ. Ý tưởng đơn giản: dữ liệu = tập các bảng (relation), mỗi bảng có dòng (tuple) và cột (attribute).
Sự đơn giản này có 3 sức mạnh:
- Declarative — bạn nói cần gì (SELECT name FROM users WHERE age > 18), không cần nói làm thế nào. DB tự tối ưu.
- Toán học chặt chẽ — dựa trên đại số quan hệ và tính toán quan hệ → tối ưu hóa, biến đổi truy vấn được chứng minh đúng.
- JOIN linh hoạt — kết hợp nhiều bảng theo nhiều cách mà schema không cần biết trước.
users
- ★ idBIGINT
- emailVARCHAR
- created_atTIMESTAMP
orders
- ★ idBIGINT
- → user_idBIGINT
- totalDECIMAL
- statusENUM
order_items
- ★ idBIGINT
- → order_idBIGINT
- → product_idBIGINT
- qtyINT
Ba bảng trên — một schema kinh điển — có thể trả lời được: tổng doanh thu của user X, top 10 sản phẩm bán chạy,
đơn hàng pending lâu nhất, v.v. — chỉ với SQL JOIN + GROUP BY.
4. ACID — bốn chữ định nghĩa "đáng tin"
| Letter | Tên | Ý nghĩa | Ví dụ |
| A |
Atomicity |
"Tất cả hoặc không gì cả". Một transaction không thể chỉ thực thi nửa chừng. |
Chuyển tiền A→B: trừ A và cộng B phải cùng commit hoặc cùng rollback. |
| C |
Consistency |
Sau transaction, mọi integrity constraint (FK, CHECK, UNIQUE) đều thỏa. |
Không tồn tại order với user_id không có trong bảng users. |
| I |
Isolation |
Các transaction chạy đồng thời như thể chạy tuần tự (ở mức Serializable). |
Hai user cùng book ghế cuối cùng — chỉ một thành công. |
| D |
Durability |
Sau COMMIT, dữ liệu sống sót qua mọi crash (kể cả mất điện ngay sau đó). |
Nhờ Write-Ahead Log (WAL) ghi xuống disk trước khi báo COMMIT thành công. |
5. SQL vs NoSQL — chọn cái gì?
SQL — chọn khi
- Dữ liệu có cấu trúc rõ, schema ổn định.
- Cần JOIN nhiều bảng linh hoạt, ad-hoc query.
- Cần ACID mạnh — tài chính, đặt hàng, booking.
- Đội nhỏ → 1 instance Postgres scale rất xa (TB-scale).
- Báo cáo BI, analytics tạm thời.
NoSQL — chọn khi
- Schema thay đổi liên tục (CMS, IoT events, log).
- Throughput ghi cực cao, scale ngang là bắt buộc.
- Truy vấn theo key đơn giản → cache, session (Redis).
- Quan hệ phức tạp nhiều cấp (Graph DB cho social, fraud).
- Dữ liệu nested không thuần nhất (Document DB).
Anti-pattern phổ biến
Dùng MongoDB chỉ vì "schemaless nhanh". Sau 6 tháng app trưởng thành, bạn sẽ nhận ra mình đã tự cài đặt schema bằng tay
trong code — kém hơn Postgres làm sẵn cho bạn. Phần lớn dự án CRUD nên bắt đầu bằng Postgres trước.
6. CAP Theorem — không thể có cả 3
Trong hệ phân tán, khi xảy ra Network Partition (P), bạn buộc phải chọn:
- CP — Consistency over Availability: từ chối phục vụ nếu không thể đảm bảo mới nhất. Ví dụ: HBase, MongoDB (mặc định), Etcd.
- AP — Availability over Consistency: vẫn phục vụ, sẽ đồng bộ sau. Ví dụ: Cassandra, DynamoDB, CouchDB.
Lưu ý P là bắt buộc trong thực tế — network sẽ partition, đó không phải tùy chọn. Nên thực sự chỉ là chọn C vs A.
Postgres (single-node) thì không phải hệ phân tán nên CAP không áp dụng trực tiếp.
7. Các thành phần lõi của một DBMS
┌────────────────────────── POSTGRES ARCHITECTURE ──────────────────────────┐
│ │
│ Client (psql, app) │
│ │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────────────────────────────────────────┐ │
│ │ PARSER │───▶│ QUERY PLANNER / OPTIMIZER │ │
│ │ (SQL → AST) │ │ Cost-based, dùng table statistics │ │
│ └──────────────┘ └────────────────────┬─────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────┐ │
│ │ EXECUTOR │ │
│ │ Index Scan / Seq Scan / │ │
│ │ Hash Join / Merge Join │ │
│ └─────────┬──────────────────┘ │
│ │ │
│ ┌──────────────────────────────┴────────────────────────┐ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ BUFFER POOL │ ◀─────── shared_buffers ──────▶ │ STORAGE (heap, │ │
│ │ (RAM cache) │ │ index, toast) │ │
│ └──────┬───────┘ └──────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ WAL WRITER │ ──────▶ │ pg_wal/ │ ← durability, replication │
│ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ CHECKPOINTER │ │ AUTOVACUUM │ │ BG WRITER │ ← maintenance │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Mọi DBMS lớn đều có 5–7 thành phần này: parser, planner, executor, buffer pool, WAL, vacuum (GC),
và replicator. Hiểu kiến trúc giúp bạn đọc EXPLAIN tốt hơn và debug performance vấn đề thực tế.
8. Index — vì sao một câu query nhanh hơn 1000 lần
Không có index, mỗi câu WHERE email = 'a@b.com' phải quét toàn bộ bảng (Sequential Scan).
Với 10 triệu dòng = 10 triệu so sánh. Với index B-tree, chỉ cần ~24 phép so sánh (log₂(10⁷) ≈ 23.25).
Đó là khác biệt giữa 30 giây và 1 mili-giây.
Nhưng index không miễn phí:
- Tốn dung lượng disk (mỗi index thường ~10–30% kích thước bảng).
- Làm chậm INSERT/UPDATE/DELETE vì phải cập nhật cả index.
- Quá nhiều index → planner mất thời gian chọn, có khi chọn sai.
9. Replication & Sharding — scale theo chiều ngang
Replication
Sao chép cùng dữ liệu sang nhiều node để: (1) đọc song song, (2) failover, (3) backup live.
- Sync — chậm hơn, dữ liệu giống nhau tuyệt đối.
- Async — nhanh hơn, có lag nhỏ (replication lag).
- Semi-sync — ít nhất 1 replica xác nhận.
Sharding
Chia dữ liệu thành nhiều phần đặt trên nhiều node, mỗi node giữ một phần. Để scale ghi và scale dung lượng.
- Range — shard theo khoảng (id 1–1M, 1M–2M…).
- Hash — hash(key) % N → shard.
- Directory — bảng tra cứu key → shard.
10. Caching — lớp đầu tiên giảm tải DB
Trước khi nghĩ đến sharding, hãy nghĩ đến cache. Redis cho 100k–1M ops/s với latency <1ms,
đủ "che" cho 99% read traffic của hầu hết app. Hai pattern phổ biến:
- Cache-aside (Lazy loading): app đọc cache trước, miss → đọc DB → set cache.
- Write-through: ghi DB và cache cùng lúc.
- Write-behind: ghi cache trước, async flush DB sau (rủi ro mất dữ liệu).
11. OLTP vs OLAP — hai thế giới khác nhau
| Tiêu chí | OLTP (Online Transaction Processing) | OLAP (Online Analytical Processing) |
| Workload | Read/Write nhỏ, nhiều, nhanh | Aggregate trên hàng tỷ dòng, ít hơn |
| Latency | <100ms | Vài giây — vài phút OK |
| Schema | Normalized (3NF) | Star / Snowflake (denormalized) |
| Storage | Row-oriented | Column-oriented (Parquet, ORC) |
| DB | Postgres, MySQL, SQL Server | BigQuery, Snowflake, ClickHouse |
| Use case | App backend, e-commerce, banking | BI dashboard, ML training, reporting |
12. Lộ trình học đề xuất
- Tuần 1–2: Ch1–3. Cài Postgres local, viết SQL thuần thạo (JOIN, GROUP BY, CTE, Window).
- Tuần 3: Ch4–5. Thiết kế schema cho 1 ý tưởng app (đặt vé, blog, e-commerce mini).
- Tuần 4: Ch6–7. Mở 2 client psql, demo Dirty/Phantom read, thử SELECT FOR UPDATE.
- Tuần 5: Ch8. Lấy 5 query chậm, dùng EXPLAIN ANALYZE để tối ưu.
- Tuần 6: Ch9–10. Cài Redis, MongoDB. Thử shard đơn giản với 2 Postgres instance.
- Tuần 7: Ch11–12. Thiết kế hệ Caching cho 1 endpoint nóng. Thực hành migration online với
pg_repack.
Mẹo phỏng vấn
Khi gặp câu hỏi mở "Thiết kế DB cho X", luôn theo thứ tự: (1) Quy mô (read/write QPS, dung lượng, user concurrent),
(2) Truy vấn chính (top 5 query phổ biến nhất), (3) Schema (bảng + key + relation),
(4) Index (cho top query), (5) Scale (cache → read replica → shard nếu cần).
Đừng vội nói "dùng MongoDB cho linh hoạt" — đó là red flag với senior.
Sẵn sàng chưa? Bắt đầu từ Chương 1 — Database Fundamentals & Relational Model.