Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn là BA (Business Analyst) tại một ngân hàng số ở Việt Nam. Đúng 9 giờ sáng thứ Hai — giờ cao điểm khách hàng chuyển khoản, thanh toán hóa đơn, nạp tiền điện thoại — thì sếp phòng Marketing nhắn: "Chạy giúp anh báo cáo tổng giao dịch theo tỉnh trong 12 tháng qua nhé, có gấp." Bạn viết một câu truy vấn quét qua hàng chục triệu dòng giao dịch. Năm phút sau, tổng đài rung chuông: ứng dụng chuyển tiền bị chậm, khách hàng phàn nàn "quay mãi không xong", có người bấm nút hai lần vì tưởng lỗi.
Chuyện gì vừa xảy ra? Câu truy vấn báo cáo của bạn đã "giành giật" tài nguyên (CPU, bộ nhớ, khóa dữ liệu) với hệ thống giao dịch đang phục vụ khách hàng thật. Đây chính là lý do cốt lõi mà một BA làm về data modeling phải hiểu: cơ sở dữ liệu phục vụ giao dịch (OLTP) và cơ sở dữ liệu phục vụ báo cáo (Reporting) có mục tiêu, tính chất và cách thiết kế hoàn toàn khác nhau — và trong nhiều trường hợp, chúng cần được tách riêng.
Trong toàn bộ khóa học, các bài trước đã dạy bạn cách mô hình hóa entity, quan hệ, chuẩn hóa, và thậm chí ở Bài 31 bạn đã gặp Star Schema của data warehouse. Bài này không đi sâu lại kỹ thuật đó. Thay vào đó, Bài 48 trả lời một câu hỏi rất "nghiệp vụ" mà BA hay bị hỏi trong dự án thật: "Tại sao chúng ta không dùng thẳng database vận hành để làm báo cáo? Khi nào thì cần tách? Và tách ra thì đánh đổi điều gì?" Đây là kiến thức bản lề giúp bạn tham gia đúng đắn vào các quyết định kiến trúc, chứ không chỉ vẽ ERD.
Khái niệm cốt lõi
OLTP là gì?
OLTP viết tắt của Online Transaction Processing — xử lý giao dịch trực tuyến. Đây là loại cơ sở dữ liệu "chạy" hoạt động kinh doanh hằng ngày: đặt hàng, thanh toán, cập nhật tồn kho, đăng ký người dùng, ghi nhận điểm danh học viên. Nói cách khác, OLTP là nơi trạng thái hiện tại của doanh nghiệp được ghi và cập nhật liên tục.
Đặc điểm nhận dạng của một hệ OLTP:
- Nhiều thao tác ghi (insert/update/delete): hệ thống liên tục thêm giao dịch mới, cập nhật số dư, đổi trạng thái đơn hàng. Tỷ lệ ghi rất cao.
- Quan tâm trạng thái mới nhất (latest state matters): khi khách hàng xem số dư tài khoản, họ cần con số chính xác ngay lúc này, không phải của đêm qua.
- Nhiều truy vấn nhỏ, đơn giản, tần suất cao: mỗi truy vấn thường chỉ chạm vào vài dòng — "lấy đơn hàng #A123", "cập nhật tồn kho SKU X". Nhưng một giây có thể có hàng nghìn truy vấn như vậy.
- Yêu cầu độ trễ cực thấp: người dùng cuối chờ tính bằng mili-giây.
- Được chuẩn hóa cao (thường 3NF): để tránh dư thừa và bất nhất khi ghi. Bạn đã học điều này ở Bài 12–14.
- Đề cao tính toàn vẹn giao dịch (ACID): một lệnh chuyển tiền hoặc thành công trọn vẹn, hoặc không xảy ra gì cả.
Reporting Database là gì?
Reporting Database (cơ sở dữ liệu báo cáo, đôi khi gọi là OLAP — Online Analytical Processing khi ở quy mô phân tích) được thiết kế để đọc và tổng hợp lượng lớn dữ liệu phục vụ ra quyết định: doanh thu theo tháng, top sản phẩm bán chạy, tỷ lệ khách hàng rời bỏ, phân tích hành vi theo khu vực.
Đặc điểm nhận dạng:
- Chủ yếu là đọc (read-heavy): rất ít ghi trực tiếp; dữ liệu được nạp vào theo lô (batch) từ OLTP.
- Quan tâm dữ liệu lịch sử, xu hướng theo thời gian: không chỉ "hôm nay bao nhiêu" mà "12 tháng qua thay đổi ra sao".
- Ít truy vấn nhưng mỗi truy vấn rất "nặng": quét hàng triệu dòng, GROUP BY, JOIN nhiều bảng, tính tổng/trung bình.
- Chấp nhận độ trễ dữ liệu (data latency): báo cáo cập nhật đến hết ngày hôm qua thường là đủ tốt. Người xem báo cáo không cần con số của 2 giây trước.
- Thường được phi chuẩn hóa (denormalized): gộp bảng, thêm cột tính sẵn để truy vấn nhanh — đây là ứng dụng thực tế của Bài 15 (Denormalization) và Bài 31 (Star Schema).
Vì sao phải tách riêng?
Đây là phần trọng tâm. Có bốn lý do lớn:
1. Tranh chấp tài nguyên (resource contention). Như câu chuyện mở đầu: một truy vấn báo cáo nặng có thể khóa bảng, chiếm CPU và bộ nhớ, làm chậm giao dịch của khách hàng thật. Tách riêng nghĩa là báo cáo chạy trên "máy" khác, không đụng đến hệ thống đang phục vụ tiền bạc.
2. Mâu thuẫn về thiết kế tối ưu. OLTP muốn chuẩn hóa cao để ghi nhanh và an toàn. Reporting muốn phi chuẩn hóa để đọc nhanh. Cùng một database không thể tối ưu đồng thời cho cả hai — đây là mâu thuẫn kiến trúc căn bản, không phải chuyện chỉnh index là xong.
3. Chiến lược đánh index khác nhau. OLTP cần ít index để ghi nhanh (mỗi index làm chậm insert/update — bạn sẽ hiểu sâu hơn ở Bài 23). Reporting cần nhiều index và cấu trúc tổng hợp để đọc nhanh. Hai triết lý ngược nhau.
4. Bảo mật và phân quyền. Nhân viên phân tích cần đọc rộng nhiều bảng để làm báo cáo, nhưng bạn không muốn cấp quyền đó trên database vận hành chứa dữ liệu nhạy cảm và đang chạy giao dịch. Tách riêng giúp khoanh vùng rủi ro.
Các mức độ tách — không phải "được ăn cả ngã về không"
BA cần biết rằng "tách reporting khỏi OLTP" là một dải quang phổ, không phải công tắc bật/tắt:
- Mức 0 — Dùng chung, chạy giờ thấp điểm: báo cáo chạy trực tiếp trên OLTP nhưng hẹn giờ ban đêm. Rẻ, đơn giản, chỉ hợp với dữ liệu nhỏ.
- Mức 1 — Read Replica (bản sao chỉ đọc): tạo một bản sao gần thời gian thực của OLTP, chỉ dùng để đọc. Báo cáo chạy trên bản sao, không đụng bản chính. Đây là bước tách phổ biến và ít tốn công nhất.
- Mức 2 — Reporting Database phi chuẩn hóa riêng: một database riêng, cấu trúc được thiết kế lại cho báo cáo (view tổng hợp, bảng gộp), nạp dữ liệu định kỳ qua ETL/ELT.
- Mức 3 — Data Warehouse đầy đủ: Star Schema, fact & dimension, phục vụ phân tích quy mô lớn (chủ đề của Bài 31).
Tình huống thực tế
Tình huống 1 — Ngân hàng số bị "nghẽn" vì báo cáo
Bối cảnh: Một ngân hàng số giả định tại Việt Nam, tạm gọi là "VBank", có khoảng 2 triệu khách hàng và xử lý trung bình 8 triệu giao dịch mỗi ngày trên hệ core banking (OLTP, chuẩn hóa 3NF). Phòng Kinh doanh yêu cầu một dashboard "doanh số theo chi nhánh và tỉnh, cập nhật liên tục".
Diễn giải: Đội IT ban đầu cho dashboard truy vấn thẳng database vận hành. Mỗi lần dashboard refresh, câu truy vấn JOIN bảng giao_dich (hơn 2 tỷ dòng lịch sử) với khach_hang và chi_nhanh, GROUP BY theo tỉnh. Vào giờ cao điểm, thời gian phản hồi của tính năng chuyển khoản tăng từ 200ms lên hơn 3 giây. Bộ phận vận hành phát hiện các truy vấn báo cáo đang giữ khóa đọc kéo dài và ngốn bộ nhớ đệm.
Giải pháp: VBank dựng một read replica cập nhật trễ khoảng 30 giây, chuyển toàn bộ dashboard sang đọc từ replica. Với các báo cáo lịch sử 12 tháng, họ nạp dữ liệu tổng hợp sẵn xuống một reporting database chạy ETL mỗi đêm. Kết quả: giao dịch quay lại 200ms, còn báo cáo "cập nhật liên tục" trễ 30 giây — hoàn toàn chấp nhận được với bối cảnh kinh doanh.
Bài học: "Cập nhật liên tục" mà nghiệp vụ mong muốn thường không có nghĩa là "chính xác đến từng mili-giây". BA cần đào sâu yêu cầu để biết độ trễ nào là chấp nhận được — chính con số này quyết định chọn mức tách nào.
Tình huống 2 — Sàn thương mại điện tử và báo cáo "sai số"
Bối cảnh: Một sàn TMĐT giả định "ShopVN" tách reporting database từ lâu. Dữ liệu OLTP đơn hàng được đổ sang reporting mỗi đêm lúc 2 giờ sáng. Một sáng nọ, Giám đốc vận hành hỏi: "Sao báo cáo doanh thu hôm nay thấp hơn con số phòng chăm sóc khách hàng đang nói?"
Diễn giải: Không ai làm sai cả. Báo cáo phản ánh dữ liệu tính đến 2 giờ sáng — tức là hết ngày hôm trước. Phòng CSKH lại nhìn số liệu trực tiếp trên OLTP theo thời gian thực. Đây là hệ quả tự nhiên của data latency: reporting database luôn "trễ" một nhịp so với OLTP. Vấn đề không nằm ở dữ liệu, mà ở chỗ không ai truyền đạt rõ "mốc thời gian" của báo cáo.
Giải pháp: BA bổ sung vào mọi dashboard một dòng nhãn rõ ràng: "Dữ liệu cập nhật đến 02:00 ngày DD/MM" và ghi rõ trong data dictionary (Bài 17) về chu kỳ làm mới. Ngoài ra, những con số cần "sống" như tồn kho thời gian thực thì được lấy từ replica gần realtime, tách khỏi báo cáo tổng hợp theo ngày.
Bài học: Khi tách reporting, bạn tạo ra hai "sự thật" ở hai mốc thời gian khác nhau. Trách nhiệm của BA là làm cho độ trễ trở nên minh bạch, tránh cãi nhau "số của ai đúng".
Tình huống 3 — Startup dùng chung một database quá lâu
Bối cảnh: Một startup EdTech giả định "HocNhanh" với LMS phục vụ 50.000 học viên. Giai đoạn đầu, họ dùng đúng một database cho cả vận hành lẫn báo cáo — hoàn toàn hợp lý khi dữ liệu còn nhỏ. Sau hai năm, dữ liệu tiến độ học tập phình lên, và các báo cáo cho đối tác doanh nghiệp (B2B) bắt đầu làm chậm giao diện học viên vào cuối tháng — đúng lúc chốt số.
Diễn giải: Điểm mấu chốt ở đây là thời điểm tách. Tách quá sớm khi còn nhỏ là lãng phí (thêm hạ tầng, thêm ETL, thêm chỗ hỏng). Nhưng để quá muộn thì trả giá bằng trải nghiệm người dùng và những đêm trực khắc phục sự cố.
Giải pháp: HocNhanh chọn giải pháp trung gian ít tốn kém: một read replica cho toàn bộ báo cáo B2B, giữ OLTP sạch cho trải nghiệm học viên. Họ chưa vội xây data warehouse vì nhu cầu phân tích chưa đủ phức tạp.
Bài học: "Có nên tách không" luôn phải gắn với quy mô và giai đoạn. BA giỏi không mặc định "phải tách", mà giúp đội ra quyết định đúng thời điểm dựa trên tín hiệu thực tế (báo cáo bắt đầu ảnh hưởng vận hành).
Hướng dẫn từng bước
Khi bạn tham gia một dự án và cần đánh giá "có nên tách reporting khỏi OLTP không", hãy đi theo trình tự sau:
Bước 1 — Liệt kê các nhu cầu báo cáo và phân loại. Với mỗi báo cáo, hỏi: nó cần dữ liệu thời gian thực hay có thể trễ? Nó quét nhiều dòng hay ít dòng? Chạy tần suất nào? Ai xem? Bảng phân loại này là đầu vào cho mọi quyết định sau.
Bước 2 — Xác định độ trễ chấp nhận được (acceptable latency). Đây là câu hỏi nghiệp vụ quan trọng nhất. Ngồi với người dùng và làm rõ: "Nếu báo cáo trễ 1 giờ thì có sao không? Trễ đến hết ngày hôm qua thì sao?" Câu trả lời quyết định bạn cần replica gần realtime hay chỉ cần ETL đêm.
Bước 3 — Đo mức độ ảnh hưởng lên OLTP hiện tại. Phối hợp với đội kỹ thuật xem các truy vấn báo cáo hiện có đang làm chậm hệ vận hành đến mức nào. Nếu chưa ảnh hưởng và dữ liệu nhỏ, có thể chưa cần tách vội.
Bước 4 — Chọn mức tách phù hợp. Dựa trên ba bước trên, đề xuất Mức 0–3 như đã nêu. Nguyên tắc: chọn mức đơn giản nhất đáp ứng được nhu cầu, tránh "đao to búa lớn".
Bước 5 — Thiết kế mô hình cho reporting (nếu tách hẳn). Nếu chọn Mức 2–3, đây là lúc áp dụng phi chuẩn hóa: gộp bảng, thêm cột tính sẵn, thiết kế bảng tổng hợp theo ngày/tháng. Nhớ rằng bạn đang tối ưu cho đọc, khác hẳn tư duy chuẩn hóa của OLTP.
Bước 6 — Xác định chu kỳ và cách đồng bộ dữ liệu. Batch ban đêm? Gần realtime qua replica? Ghi lại rõ ràng ai chịu trách nhiệm khi đồng bộ lỗi.
Bước 7 — Ghi tài liệu và truyền đạt độ trễ. Cập nhật data dictionary, ghi rõ mốc thời gian dữ liệu trên mọi báo cáo. Đây là bước hay bị bỏ quên nhưng cứu bạn khỏi vô số tranh cãi "số ai đúng".
Lỗi thường gặp & mẹo
Lỗi 1 — Cho báo cáo chạy thẳng trên OLTP production giờ cao điểm. Đây là lỗi kinh điển, gây chậm hệ thống thật. Mẹo: tối thiểu hãy chuyển sang read replica, hoặc hẹn lịch giờ thấp điểm nếu dữ liệu còn nhỏ.
Lỗi 2 — Kỳ vọng reporting database luôn khớp OLTP đến từng giây. Sau khi tách, hai bên gần như luôn lệch nhau vì độ trễ. Mẹo: đừng coi lệch là "bug"; hãy công khai mốc thời gian dữ liệu trên báo cáo.
Lỗi 3 — Bê nguyên cấu trúc chuẩn hóa 3NF của OLTP sang reporting. Truy vấn báo cáo sẽ phải JOIN quá nhiều bảng và chạy chậm. Mẹo: reporting nên phi chuẩn hóa có chủ đích cho tốc độ đọc.
Lỗi 4 — Tách quá sớm khi dữ liệu còn nhỏ. Tự dựng data warehouse cho một app vài nghìn dòng là lãng phí và tăng điểm hỏng. Mẹo: bắt đầu đơn giản, tách khi có tín hiệu thực tế (báo cáo bắt đầu ảnh hưởng vận hành).
Lỗi 5 — Tách nhưng không ai quản lý việc đồng bộ. ETL đêm lỗi mà không ai biết, sáng ra báo cáo sai. Mẹo: luôn có cảnh báo khi đồng bộ thất bại và người chịu trách nhiệm rõ ràng.
Mẹo vàng cho BA: Khi nghe stakeholder nói "cần realtime", đừng gật đầu ngay. Hãy hỏi lại "realtime để làm gì, quyết định gì phụ thuộc vào nó?". Rất thường xuyên, "realtime" thực chất là "đủ mới trong hôm nay" — và điều đó tiết kiệm rất nhiều chi phí hạ tầng.
Bài tập thực hành
Bài tập 1 — Phân loại truy vấn. Cho các nhu cầu sau, hãy đánh dấu mỗi cái thuộc OLTP hay Reporting và giải thích ngắn: (a) Khách hàng kiểm tra số dư tài khoản. (b) Giám đốc xem doanh thu theo quý của 3 năm. (c) Cập nhật trạng thái đơn hàng thành "đã giao". (d) Phân tích top 10 sản phẩm bán chạy theo tỉnh trong 6 tháng. (e) Trừ tồn kho khi khách đặt hàng.
Bài tập 2 — Tình huống ra quyết định. Một chuỗi cửa hàng tiện lợi có 300 cửa hàng, mỗi ngày ~500.000 giao dịch. Ban giám đốc muốn một dashboard doanh thu "cập nhật gần thời gian thực" và một bộ báo cáo phân tích xu hướng theo tháng. Hãy đề xuất mức tách (0–3) cho từng loại báo cáo, và nêu độ trễ bạn sẽ hỏi để làm rõ với stakeholder.
Bài tập 3 — Viết nhãn độ trễ. Giả sử reporting database của bạn nạp dữ liệu qua ETL lúc 3 giờ sáng mỗi ngày. Hãy viết một dòng nhãn ngắn gọn (tiếng Việt) sẽ hiển thị trên mọi dashboard để người xem hiểu rõ mốc thời gian dữ liệu, đồng thời viết mô tả tương ứng trong data dictionary.
Gợi ý đáp án Bài tập 1: (a) OLTP — đọc trạng thái mới nhất, một dòng; (b) Reporting — tổng hợp lịch sử; (c) OLTP — ghi/cập nhật; (d) Reporting — tổng hợp nhiều dòng theo thời gian; (e) OLTP — ghi, cần toàn vẹn giao dịch.
Tóm tắt
Bài này trả lời một câu hỏi nghiệp vụ then chốt: tại sao và khi nào phải tách cơ sở dữ liệu báo cáo khỏi cơ sở dữ liệu giao dịch.
- OLTP phục vụ vận hành hằng ngày: nhiều thao tác ghi, quan tâm trạng thái mới nhất, nhiều truy vấn nhỏ và nhanh, chuẩn hóa cao, đề cao toàn vẹn giao dịch.
- Reporting phục vụ ra quyết định: chủ yếu đọc, quan tâm dữ liệu lịch sử và xu hướng, ít truy vấn nhưng mỗi cái rất nặng, chấp nhận độ trễ, thường phi chuẩn hóa.
- Bốn lý do tách: tranh chấp tài nguyên, mâu thuẫn thiết kế tối ưu, chiến lược index khác nhau, và bảo mật/phân quyền.
- Việc tách là một dải quang phổ (Mức 0 đến Mức 3), không phải công tắc bật/tắt. Chọn mức đơn giản nhất đáp ứng được nhu cầu.
- Vai trò của BA: làm rõ độ trễ chấp nhận được, phân loại nhu cầu báo cáo, chọn đúng thời điểm tách, và luôn truyền đạt minh bạch mốc thời gian dữ liệu để tránh tranh cãi "số ai đúng".