Menu
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Đang tải...

SQL vs NoSQL: chọn loại database

API and Technical Fundamentals cho BA Bài 32/60

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn là BA của một startup giao đồ ăn tại TP.HCM. Trong buổi họp đầu sprint, kỹ sư backend hỏi bạn một câu tưởng đơn giản: "Đơn hàng mình lưu vào Postgres hay Mongo?" Cả phòng nhìn về phía bạn. Nếu bạn lắc đầu "cái này em không rành công nghệ", bạn vừa đánh mất một cơ hội lớn để định hình sản phẩm. Bởi vì câu hỏi đó không chỉ là kỹ thuật — nó quyết định việc báo cáo doanh thu có chính xác từng đồng hay không, việc thêm một loại khuyến mãi mới mất một ngày hay một tháng, và việc hệ thống còn trụ vững khi đơn hàng tăng gấp mười lần vào dịp Tết.

Là BA, bạn không cần tự tay cài đặt database. Nhưng bạn là người hiểu rõ nhất "dữ liệu này dùng để làm gì, đọc nhiều hay ghi nhiều, có cần chính xác tuyệt đối không". Đó chính là những yếu tố quyết định nên chọn SQL hay NoSQL. Một BA biết đặt đúng câu hỏi về dữ liệu sẽ giúp đội kỹ thuật chọn đúng nền tảng ngay từ đầu — và tránh được những cuộc "migrate database" đau đớn kéo dài hàng quý sau này.

Bài này tập trung vào cách phân biệt và lựa chọn giữa SQL và NoSQL. Chúng ta sẽ không đi sâu vào MongoDB hay Redis (những bài sau sẽ làm việc đó), mà tập trung vào bộ tiêu chí giúp bạn — với vai trò BA — đưa ra quyết định và bảo vệ quyết định đó trong phòng họp.

Khái niệm cốt lõi

SQL — cơ sở dữ liệu quan hệ (Relational Database)

SQL Database (còn gọi là RDBMS — Relational Database Management System) tổ chức dữ liệu thành bảng (table) gồm các hàng (row) và cột (column), giống hệt một bảng tính Excel có kỷ luật. Những cái tên bạn sẽ gặp nhiều: MySQL, PostgreSQL, SQL Server (Microsoft), Oracle.

Đặc trưng cốt lõi của SQL:

  • Schema cố định (fixed schema): Trước khi nhập dữ liệu, bạn phải định nghĩa trước cấu trúc — bảng khach_hang có cột nào, kiểu dữ liệu gì (số, chuỗi, ngày). Mọi hàng đều phải tuân theo khuôn này. Cột email đã khai là chuỗi thì không thể nhét số vào.
  • Quan hệ và JOIN: Dữ liệu được tách thành nhiều bảng để tránh trùng lặp. Bảng don_hang không chứa luôn tên và địa chỉ khách, mà chỉ giữ một khach_hang_id trỏ sang bảng khach_hang. Khi cần xem đầy đủ, ta dùng phép JOIN để ghép các bảng lại. Cách tách này gọi là chuẩn hóa (normalization).
  • ACID transactions: Đây là điểm vàng của SQL. ACID gồm bốn tính chất: Atomicity (một giao dịch hoặc thành công trọn vẹn, hoặc không xảy ra gì cả), Consistency (dữ liệu luôn ở trạng thái hợp lệ), Isolation (các giao dịch chạy đồng thời không giẫm chân nhau), Durability (đã commit là không mất). Khi chuyển tiền từ tài khoản A sang B, không bao giờ có chuyện trừ tiền A xong mà chưa cộng vào B.
  • Strong consistency (nhất quán mạnh): Vừa ghi xong, đọc lại lập tức thấy giá trị mới ngay. Không có độ trễ.

NoSQL — cơ sở dữ liệu phi quan hệ

NoSQL ("Not Only SQL") là tên gọi chung cho nhiều loại database không dùng mô hình bảng truyền thống. Có bốn nhánh chính:

  • Document database: Lưu dữ liệu dạng tài liệu JSON. Ví dụ: MongoDB, Couchbase. Một đơn hàng được lưu nguyên cục, kèm luôn thông tin khách và danh sách sản phẩm bên trong — không cần JOIN.
  • Key-Value store: Đơn giản như một cuốn từ điển khổng lồ, mỗi khóa (key) ứng với một giá trị (value). Ví dụ: Redis, DynamoDB. Cực nhanh, hợp cho cache và session.
  • Wide-column store: Tối ưu cho lượng dữ liệu cực lớn theo cột. Ví dụ: Cassandra, HBase.
  • Graph database: Lưu các mối quan hệ phức tạp như mạng xã hội, gợi ý bạn bè. Ví dụ: Neo4j.
Đặc trưng chung của NoSQL:

  • Schema linh hoạt (flexible/schemaless): Mỗi bản ghi có thể có cấu trúc khác nhau. Hôm nay đơn hàng có thêm trường ma_giam_gia, ngày mai thêm ghi_chu_shipper — không cần "sửa bảng" như SQL.
  • Mở rộng theo chiều ngang (horizontal scaling): Khi tải tăng, ta thêm nhiều máy chủ thường (nhân bản dữ liệu ra nhiều server) thay vì phải mua một máy chủ siêu mạnh. NoSQL được thiết kế để làm việc này dễ dàng.
  • Eventual consistency (nhất quán cuối cùng): Nhiều hệ NoSQL chấp nhận độ trễ nhỏ — vừa ghi vào một server, vài mili-giây sau các server khác mới đồng bộ. Đổi lại tốc độ và khả năng chịu tải cao.

So sánh nhanh để ghi nhớ

Tiêu chíSQLNoSQL
Cấu trúcBảng, schema cố địnhDocument/key-value, schema linh hoạt
Quan hệJOIN nhiều bảngLồng dữ liệu (nested), ít JOIN
Giao dịchACID mạnhThường ưu tiên tốc độ hơn ACID
Nhất quánStrong consistencyThường eventual consistency
Mở rộngChiều dọc (máy mạnh hơn)Chiều ngang (thêm máy)
Hợp vớiDữ liệu có cấu trúc, cần chính xácDữ liệu thay đổi nhanh, quy mô lớn

Một hiểu lầm cần xóa bỏ ngay

NoSQL không "mới hơn" hay "tốt hơn" SQL. Đây không phải cuộc chiến cũ-mới. Đây là chuyện chọn đúng công cụ cho đúng việc. Một hệ thống thực tế thường dùng cả hai cùng lúc: Postgres cho dữ liệu giao dịch quan trọng, Redis cho cache, MongoDB cho log. Người ta gọi đây là polyglot persistence — dùng nhiều loại database trong cùng một sản phẩm.

Tình huống thực tế

Tình huống 1: Ví điện tử và lằn ranh không được phép sai

Một công ty fintech tại Hà Nội xây ví điện tử, dự kiến 2 triệu người dùng. Đội phát triển trẻ, mê công nghệ mới, ban đầu muốn dùng MongoDB cho mọi thứ vì "linh hoạt, dễ scale, hợp xu hướng".

BA của dự án đặt một câu hỏi đắt giá trong buổi review: "Khi người dùng A chuyển 500.000đ cho người dùng B, nếu hệ thống trừ tiền A xong rồi sập ngay trước khi cộng cho B, thì sao?" Cả đội im lặng. Với eventual consistency và việc thiếu giao dịch ACID đa-bảng chặt chẽ, kịch bản "tiền bốc hơi" hoàn toàn có thể xảy ra trong điều kiện tải cao.

Kết quả: đội chọn PostgreSQL cho phần lõi ví — số dư, lịch sử giao dịch, đối soát — vì ở đây ACID và strong consistency là bắt buộc, không thương lượng. Riêng phần feed thông báo và lịch sử hành vi (ít quan trọng nếu trễ vài giây) thì để cho một NoSQL khác.

Bài học: Khi dữ liệu liên quan đến tiền, số dư, kế toán hay bất cứ thứ gì "sai một đồng là chết", SQL với ACID gần như luôn là lựa chọn đúng. BA chính là người phải nêu bật yêu cầu nghiệp vụ "tính toàn vẹn tài chính" để cả đội thấy rõ.

Tình huống 2: Sàn thương mại điện tử và bài toán catalog muôn hình vạn trạng

Một sàn TMĐT kiểu Tiki/Shopee tại Việt Nam có catalog sản phẩm cực kỳ đa dạng: điện thoại có thuộc tính RAM, pin, màn hình; áo thun có size, màu, chất liệu; sách có tác giả, NXB, số trang. Nếu ép tất cả vào một bảng SQL cố định, bạn sẽ có một bảng với hàng trăm cột mà mỗi sản phẩm chỉ dùng được vài cột — phần còn lại để trống (NULL) lãng phí và rối rắm.

Đội kỹ thuật chọn MongoDB cho phần catalog sản phẩm. Mỗi sản phẩm là một document JSON với cấu trúc riêng: điện thoại lưu trường dung_luong_pin, áo thun lưu mảng size: ["S","M","L"]. Thêm loại sản phẩm mới với thuộc tính lạ? Chỉ việc thêm trường vào document, không cần đụng tới schema toàn hệ thống.

Nhưng lưu ý quan trọng: phần đơn hàng và thanh toán của chính sàn này vẫn nằm trên SQL. Catalog có thể linh hoạt, nhưng tiền thì không. Đây chính là polyglot persistence trong thực tế.

Bài học: Khi cấu trúc dữ liệu thay đổi liên tục, mỗi bản ghi mỗi khác, và bạn cần đọc nhanh nguyên cục dữ liệu mà không JOIN — Document NoSQL tỏa sáng. BA cần nhận diện đặc tính "dữ liệu đa dạng, tiến hóa nhanh" để gợi ý đúng hướng.

Tình huống 3: Giỏ hàng phiên live-stream và tốc độ là tất cả

Một startup bán hàng qua live-stream ở Đông Nam Á gặp hiện tượng: trong các phiên live của KOL, hàng chục nghìn người cùng lúc bấm "thêm vào giỏ" trong vài phút. Database SQL chính bắt đầu chậm vì mỗi lần cập nhật giỏ hàng đều ghi xuống đĩa, kèm kiểm tra ràng buộc.

Giải pháp: dùng Redis (key-value, lưu trên RAM) làm nơi giữ giỏ hàng tạm thời trong phiên live. Mỗi giỏ hàng là một key (theo user ID), thao tác thêm/bớt diễn ra trong vài mili-giây. Chỉ khi người dùng bấm "thanh toán", dữ liệu mới được ghi xuống database SQL chính thức.

Bài học: Với dữ liệu tạm thời, đọc-ghi cực nhiều, chấp nhận mất mát nhỏ và cần tốc độ tối đa — key-value NoSQL như Redis là vũ khí. BA cần nắm yêu cầu phi chức năng (non-functional) như "phải chịu được X nghìn thao tác/giây" để biết khi nào tốc độ quan trọng hơn sự bền vững tuyệt đối.

Hướng dẫn từng bước

Khi đứng trước quyết định "SQL hay NoSQL", BA có thể dẫn dắt đội qua các bước sau:

Bước 1 — Mô tả bản chất dữ liệu. Dữ liệu này có cấu trúc rõ ràng và ổn định không? Có nhiều mối quan hệ chằng chịt giữa các thực thể (khách hàng ↔ đơn hàng ↔ sản phẩm) không? Nếu có cấu trúc rõ và nhiều quan hệ → nghiêng về SQL.

Bước 2 — Xác định yêu cầu nhất quán. Hỏi: "Nếu dữ liệu sai lệch vài giây thì hậu quả là gì?" Nếu câu trả lời là "mất tiền, sai pháp lý, sai kế toán" → cần ACID → SQL. Nếu là "không sao, người dùng không nhận ra" → NoSQL chấp nhận được.

Bước 3 — Ước lượng quy mô và kiểu truy cập. Bao nhiêu bản ghi? Đọc nhiều hay ghi nhiều? Cần đọc nguyên cục một đối tượng (NoSQL document tốt) hay cần truy vấn phân tích phức tạp, gộp nhóm, báo cáo chéo bảng (SQL mạnh hơn)?

Bước 4 — Đánh giá tốc độ tiến hóa của schema. Cấu trúc dữ liệu có thay đổi xoành xoạch theo từng tính năng mới không? Nếu schema biến động liên tục, NoSQL linh hoạt giúp đỡ tốn công migrate.

Bước 5 — Cân nhắc kết hợp. Đừng ép buộc "chỉ một loại". Hỏi đội: "Liệu ta có thể dùng SQL cho phần lõi giao dịch và NoSQL cho phần cache/log/catalog không?" Phần lớn hệ thống trưởng thành đều dùng kết hợp.

Bước 6 — Ghi lại quyết định. Viết một đoạn ngắn trong tài liệu (kiểu ADR — Architecture Decision Record): chọn gì, vì lý do nghiệp vụ nào. Sau này khi có người hỏi "sao hồi đó chọn cái này", bạn có câu trả lời.

Lỗi thường gặp & mẹo

Lỗi 1 — Chọn theo trào lưu. "NoSQL hiện đại hơn nên dùng NoSQL." Đây là cái bẫy phổ biến nhất. Nhiều startup chọn MongoDB cho dữ liệu giao dịch tài chính rồi phải khổ sở migrate sang Postgres sau một năm. Hãy chọn theo yêu cầu nghiệp vụ, không theo tweet thịnh hành.

Lỗi 2 — Nghĩ NoSQL không có schema thì khỏi cần thiết kế. Schema linh hoạt không có nghĩa là không cần kỷ luật. Nếu mỗi lập trình viên đặt tên trường một kiểu (userName, user_name, uname), dữ liệu sẽ thành đống hỗn loạn. NoSQL vẫn cần một "schema ngầm" thống nhất.

Lỗi 3 — Tưởng SQL không scale được. SQL hiện đại (PostgreSQL, MySQL) scale rất tốt cho phần lớn nhu cầu doanh nghiệp Việt Nam. Đừng vội bỏ SQL chỉ vì sợ "không chịu nổi tải". Trừ phi bạn ở quy mô Facebook, SQL thường thừa sức.

Lỗi 4 — Quên rằng JOIN trong NoSQL rất tốn công. NoSQL document né JOIN bằng cách lồng dữ liệu, nhưng khi bạn thực sự cần ghép nhiều loại dữ liệu để báo cáo, NoSQL trở nên vụng về. Nếu nghiệp vụ cần nhiều báo cáo phân tích chéo, SQL dễ thở hơn nhiều.

Mẹo cho BA: Khi viết user story hay yêu cầu, hãy thêm các yêu cầu phi chức năng về dữ liệu: "Số dư phải chính xác tuyệt đối", "Hệ thống phải chịu 5.000 đơn/phút giờ cao điểm", "Cấu trúc khuyến mãi sẽ thay đổi hàng tháng". Chính những câu này dẫn đội tới quyết định database đúng đắn — và đó là giá trị bạn mang lại.

Mẹo phỏng vấn: Câu "Khi nào dùng SQL, khi nào dùng NoSQL?" gần như chắc chắn xuất hiện. Trả lời ăn điểm: nêu trade-off (consistency vs tốc độ, schema cố định vs linh hoạt) và cho một ví dụ kết hợp, thay vì phán "cái này tốt hơn cái kia".

Bài tập thực hành

  • Phân loại dữ liệu: Với một app gọi xe kiểu Grab, liệt kê 5 loại dữ liệu (ví dụ: thông tin chuyến đi, vị trí tài xế thời gian thực, ví tiền, đánh giá, log thông báo). Với mỗi loại, ghi rõ nên SQL hay NoSQL và viết một câu lý do dựa trên yêu cầu nghiệp vụ.
  • Đặt câu hỏi đúng: Soạn 5 câu hỏi bạn sẽ hỏi product owner để quyết định một feature mới (ví dụ: chương trình tích điểm) nên lưu vào loại database nào. Mỗi câu hỏi phải nhắm vào một tiêu chí: nhất quán, quy mô, độ biến động schema, kiểu truy vấn, tốc độ.
  • Phản biện một quyết định: Một bạn dev đề xuất lưu toàn bộ hệ thống kế toán nội bộ vào MongoDB "cho linh hoạt". Viết một đoạn 4-5 câu phản biện lịch sự, nêu rủi ro về ACID và đề xuất hướng thay thế hợp lý.
  • Vẽ kiến trúc kết hợp: Phác thảo (bằng lời hoặc sơ đồ) một hệ thống TMĐT dùng polyglot persistence: chỉ rõ phần nào dùng SQL, phần nào dùng NoSQL, và tại sao.

Tóm tắt

  • SQL (MySQL, PostgreSQL, SQL Server, Oracle): bảng + schema cố định, JOIN nhiều bảng, giao dịch ACID, strong consistency. Hợp với dữ liệu có cấu trúc, nhiều quan hệ, và bắt buộc chính xác — đặc biệt là tiền bạc, kế toán, giao dịch.
  • NoSQL (MongoDB, Redis, Cassandra, Neo4j): schema linh hoạt, mở rộng theo chiều ngang, thường ưu tiên tốc độ và quy mô hơn nhất quán tuyệt đối. Hợp với dữ liệu đa dạng, tiến hóa nhanh, tải lớn, hoặc cần tốc độ cực cao (cache, session, catalog, log).
  • Không có loại nào "tốt hơn" tuyệt đối — chỉ có loại phù hợp hơn với từng nhu cầu. Hệ thống trưởng thành thường dùng kết hợp (polyglot persistence).
  • Vai trò của BA: không phải chọn database thay kỹ sư, mà là làm rõ yêu cầu nghiệp vụ về dữ liệu — tính nhất quán, quy mô, kiểu truy vấn, độ biến động — để cả đội ra quyết định đúng. Một câu hỏi đúng lúc của BA có thể cứu dự án khỏi một cuộc migrate database tốn kém hàng tháng trời.
Ở các bài tiếp theo, chúng ta sẽ đi sâu vào từng loại NoSQL cụ thể (MongoDB ở Bài 33, Redis ở Bài 34) để bạn hiểu kỹ hơn cách chúng vận hành. Còn bây giờ, điều quan trọng nhất cần mang theo: hãy luôn bắt đầu từ bản chất của dữ liệu và yêu cầu nghiệp vụ, rồi mới chọn công cụ — chứ không phải ngược lại.