Menu
ESC

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

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

Đang tải...

Bài 31 — Data Warehouse & Star Schema

Data Modeling and ERD Mastery Bài 31/60

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

Hãy tưởng tượng bạn là BA tại một chuỗi siêu thị như WinMart. Mỗi ngày hệ thống ghi nhận hàng triệu giao dịch bán hàng. Một sáng thứ Hai, giám đốc kinh doanh nhắn bạn: "Cho anh xem doanh thu theo từng tỉnh, từng nhóm hàng, từng tháng trong 3 năm gần đây, so sánh với cùng kỳ năm trước." Bạn tự tin viết một câu truy vấn JOIN qua 8 bảng trên hệ thống bán hàng đang chạy. Kết quả: câu query chạy 40 phút, và trong lúc đó hệ thống thanh toán tại quầy bị chậm hẳn, khách hàng phàn nàn.

Đây là bài học kinh điển mà mọi data professional đều phải thấm: cơ sở dữ liệu phục vụ vận hành hằng ngày (OLTP) không được thiết kế để trả lời các câu hỏi phân tích lớn (OLAP). Hai loại tải công việc này có yêu cầu hoàn toàn khác nhau, và cố ép một hệ thống làm cả hai sẽ dẫn đến thảm hoạ về hiệu năng lẫn trải nghiệm người dùng.

Trong toàn bộ khoá học, chúng ta đã dành rất nhiều thời gian cho mô hình chuẩn hoá (normalized) phục vụ giao dịch. Bài này là một bước ngoặt tư duy: chúng ta sẽ học cách thiết kế dữ liệu cho phân tích — nơi mà nhiều nguyên tắc chuẩn hoá quen thuộc bị cố tình đảo ngược. Hiểu được Data Warehouse và mô hình Star Schema không chỉ giúp bạn thiết kế đúng, mà còn giúp bạn nói cùng ngôn ngữ với đội ngũ BI, data engineer và ban lãnh đạo khi họ cần ra quyết định dựa trên dữ liệu.

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

OLTP vs OLAP — hai thế giới khác nhau

OLTP (Online Transaction Processing) là hệ thống xử lý giao dịch trực tuyến — chính là những hệ thống vận hành mà bạn đã quen: phần mềm bán hàng, ngân hàng lõi, hệ thống đặt vé. Đặc điểm:

  • Tối ưu cho ghi và cập nhật nhiều giao dịch nhỏ, đồng thời, theo thời gian thực.
  • Chuẩn hoá cao (thường tới 3NF) để tránh dư thừa và bảo đảm tính toàn vẹn khi cập nhật.
  • Mỗi truy vấn thường chạm vào một vài bản ghi: "lấy đơn hàng số 12345", "trừ 500.000đ từ tài khoản A".
  • Câu hỏi điển hình: Khách hàng này vừa mua gì?
OLAP (Online Analytical Processing) là hệ thống xử lý phân tích trực tuyến. Đặc điểm gần như ngược lại:

  • Tối ưu cho đọc một lượng lớn dữ liệu lịch sử, tổng hợp (SUM, COUNT, AVG) theo nhiều chiều.
  • Cố tình phi chuẩn hoá (denormalized) để giảm số phép JOIN và tăng tốc đọc.
  • Mỗi truy vấn quét hàng triệu bản ghi để ra một vài con số tổng hợp.
  • Câu hỏi điển hình: Doanh thu theo vùng miền trong 3 năm qua biến động thế nào?
Một cách ví von: OLTP giống như sổ ghi chép từng giao dịch ở quầy thu ngân, còn OLAP giống như báo cáo tài chính cuối quý mà kế toán trưởng trình bày cho hội đồng quản trị.

Data Warehouse là gì

Data Warehouse (kho dữ liệu) là một cơ sở dữ liệu chuyên dụng, tập trung, được xây dựng riêng để phục vụ phân tích và báo cáo. Theo định nghĩa kinh điển của Bill Inmon, data warehouse có bốn đặc tính:

  • Subject-oriented (hướng chủ đề): tổ chức theo các chủ đề nghiệp vụ như Bán hàng, Khách hàng, Tồn kho — chứ không theo từng ứng dụng riêng lẻ.
  • Integrated (tích hợp): gom dữ liệu từ nhiều nguồn (POS, CRM, kế toán, web) và chuẩn hoá định dạng. Ví dụ giới tính ở hệ thống A lưu "M/F", hệ thống B lưu "Nam/Nữ" — khi vào kho phải thống nhất một chuẩn.
  • Time-variant (biến thiên theo thời gian): lưu dữ liệu lịch sử nhiều năm, không chỉ trạng thái hiện tại.
  • Non-volatile (không biến động): dữ liệu đã nạp vào thì không bị sửa/xoá tuỳ tiện như hệ thống vận hành; nó chỉ được thêm mới theo các chu kỳ nạp (load).
Dữ liệu đi từ hệ thống nguồn vào kho qua quy trình ETL (Extract — trích xuất, Transform — biến đổi, Load — nạp). Đây là nơi dữ liệu được làm sạch, hợp nhất và tái cấu trúc lại theo mô hình phân tích.

Star Schema — trái tim của thiết kế kho dữ liệu

Star Schema (lược đồ hình sao) là mô hình dữ liệu phổ biến nhất cho data warehouse, do Ralph Kimball phổ biến. Tên gọi xuất phát từ hình dạng: một bảng trung tâm được bao quanh bởi các bảng vệ tinh, trông như một ngôi sao. Star schema có hai loại bảng:

Fact table (bảng dữ kiện) — nằm ở trung tâm. Nó lưu các số đo (measures) có thể tính toán được: số lượng bán, doanh thu, chiết khấu, lợi nhuận. Mỗi dòng trong fact table tương ứng với một sự kiện nghiệp vụ ở mức chi tiết nhất (gọi là grain), ví dụ "một dòng hàng trong một hoá đơn". Fact table thường rất lớn (hàng trăm triệu dòng) nhưng "gầy" về số cột — chủ yếu là các khoá ngoại trỏ tới dimension và các cột số đo.

Dimension table (bảng chiều) — các bảng vệ tinh. Chúng lưu ngữ cảnh mô tả để bạn lát cắt và lọc dữ liệu: chiều Thời gian, chiều Sản phẩm, chiều Khách hàng, chiều Cửa hàng. Dimension thường nhỏ hơn nhiều nhưng "béo" về số cột, và cố tình phi chuẩn hoá — ví dụ chiều Sản phẩm gộp luôn tên ngành hàng, nhóm hàng, thương hiệu vào một bảng phẳng thay vì tách thành nhiều bảng con.

Mỗi dòng fact nối tới các dimension qua khoá thay thế (surrogate key). Khi bạn muốn "doanh thu theo nhóm hàng theo tháng", bạn JOIN fact với dimension Sản phẩm và dimension Thời gian, GROUP BY nhóm hàng và tháng. Chỉ vài phép JOIN đơn giản — đó chính là lý do star schema chạy nhanh.

Star Schema vs Snowflake Schema

Nếu bạn chuẩn hoá tiếp các dimension — tách chiều Sản phẩm thành Sản phẩm → Nhóm hàng → Ngành hàng — bạn được Snowflake Schema (lược đồ bông tuyết). Snowflake tiết kiệm dung lượng và dễ bảo trì hơn khi dữ liệu chiều thay đổi, nhưng phải JOIN nhiều bảng hơn nên thường chậm hơn và khó hiểu hơn với người dùng BI. Với đa số dự án, lời khuyên của Kimball là: ưu tiên star schema, chỉ dùng snowflake khi thực sự cần.

Tình huống thực tế

Ví dụ 1 — Chuỗi bán lẻ Bách Hoá Xanh: từ query 40 phút xuống 8 giây

Một chuỗi bán lẻ giả định mô phỏng theo Bách Hoá Xanh có khoảng 1.700 cửa hàng, ghi nhận trung bình 2 triệu dòng hoá đơn mỗi ngày. Ban đầu đội phân tích chạy báo cáo trực tiếp trên CSDL bán hàng (OLTP) được chuẩn hoá 3NF. Một báo cáo doanh thu theo tỉnh/tháng phải JOIN qua 9 bảng (hoá đơn, chi tiết hoá đơn, sản phẩm, nhóm hàng, ngành hàng, cửa hàng, quận, tỉnh, ngày) và mất gần 40 phút, đồng thời làm chậm hệ thống tại quầy.

Đội data dựng một star schema riêng. Họ tạo một fact table fact_sales ở grain "một dòng hàng trên một hoá đơn", chỉ chứa các khoá ngoại (date_key, product_key, store_key, customer_key) và các số đo (quantity, gross_amount, discount_amount, net_amount). Bao quanh là 4 dimension phẳng. Chiều dim_store gộp luôn quận, tỉnh, vùng miền vào một bảng; chiều dim_product gộp nhóm hàng, ngành hàng, thương hiệu.

Kết quả: báo cáo cũ giờ chỉ cần JOIN fact với dim_storedim_date, GROUP BY tỉnh và tháng. Thời gian chạy giảm còn khoảng 8 giây, và quan trọng hơn là chạy trên một hệ thống tách biệt nên không còn ảnh hưởng tới quầy thanh toán.

Bài học: tách biệt tải phân tích khỏi tải vận hành không phải là "tối ưu cho đẹp" — nó bảo vệ chính hệ thống kiếm tiền của doanh nghiệp.

Ví dụ 2 — Ngân hàng và bài toán Slowly Changing Dimension

Một ngân hàng giả định muốn phân tích "doanh số tín dụng theo phân khúc khách hàng". Vấn đề: một khách hàng tháng 1 thuộc phân khúc "Mass", đến tháng 6 được nâng lên "Affluent". Nếu chiều khách hàng chỉ lưu trạng thái hiện tại, thì mọi giao dịch từ tháng 1 cũng bị gán nhãn "Affluent" — sai lệch hoàn toàn bức tranh lịch sử.

Đội data áp dụng kỹ thuật Slowly Changing Dimension Type 2 (SCD2): thay vì ghi đè, họ tạo một dòng mới trong dim_customer mỗi khi phân khúc thay đổi, kèm effective_date, expiry_date và cờ is_current. Mỗi phiên bản có một surrogate key riêng. Fact table trỏ tới đúng phiên bản đang có hiệu lực tại thời điểm giao dịch. Nhờ vậy báo cáo phản ánh đúng: giao dịch tháng 1 gắn với "Mass", tháng 6 gắn với "Affluent".

Bài học: dimension không chỉ mô tả "hiện tại là gì" mà còn phải kể lại "đã từng là gì". Đây là khác biệt lớn giữa tư duy OLTP (chỉ cần trạng thái mới nhất) và tư duy OLAP (cần cả lịch sử).

Ví dụ 3 — Sàn TMĐT và chiều Thời gian được dựng sẵn

Một sàn thương mại điện tử theo phong cách Tiki muốn phân tích hành vi mua sắm theo "ngày trong tuần", "có phải ngày sale đôi 11/11 không", "thuộc quý mấy". Nếu mỗi báo cáo phải tự tính toán các thuộc tính này từ cột timestamp, vừa chậm vừa dễ sai.

Họ dựng một dimension thời gian dim_date được nạp sẵn một dòng cho mỗi ngày trong 10 năm, với hàng chục cột mô tả: day_of_week, is_weekend, month_name, quarter, fiscal_year, is_holiday, is_campaign_day. Giờ đây mọi câu hỏi về thời gian chỉ là việc lọc và GROUP BY trên các cột có sẵn, không cần hàm tính toán phức tạp.

Bài học: chiều Thời gian là dimension xuất hiện gần như trong mọi star schema, và đầu tư xây dựng nó tử tế ngay từ đầu sẽ tiết kiệm vô số công sức về sau.

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

Khi bạn được giao thiết kế một star schema, hãy đi theo bốn bước kinh điển của Kimball:

Bước 1 — Chọn quy trình nghiệp vụ (business process). Xác định rõ bạn đang mô hình hoá sự kiện gì: bán hàng, đặt hàng, trả hàng, giải ngân khoản vay. Mỗi quy trình thường tương ứng với một fact table. Đừng tham lam gộp nhiều quy trình vào một bảng.

Bước 2 — Xác định grain (mức chi tiết). Đây là bước quan trọng nhất. Hãy viết ra một câu rõ ràng: "Mỗi dòng trong fact table đại diện cho một dòng hàng trên một hoá đơn." Grain càng chi tiết, bạn càng linh hoạt khi phân tích. Quyết định grain phải làm trước khi chọn dimension hay measure.

Bước 3 — Xác định các dimension. Trả lời câu hỏi: "Người dùng muốn cắt lát dữ liệu theo những góc nào?" Mỗi câu trả lời (theo thời gian, theo sản phẩm, theo khách hàng, theo cửa hàng) là một dimension. Thiết kế dimension phẳng, mô tả đầy đủ, dùng surrogate key làm khoá chính.

Bước 4 — Xác định các measure (số đo). Liệt kê những con số có thể cộng/đếm/trung bình: số lượng, doanh thu, chiết khấu. Ưu tiên các measure additive (cộng được qua mọi chiều). Cẩn thận với measure semi-additive (như số dư tài khoản — cộng được qua khách hàng nhưng không cộng được qua thời gian) và non-additive (như tỷ lệ phần trăm — không bao giờ cộng trực tiếp).

Sau bốn bước này, bạn vẽ sơ đồ hình sao, định nghĩa khoá ngoại từ fact tới từng dimension, và thống nhất với đội ETL về nguồn dữ liệu cho mỗi cột.

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

Lỗi 1 — Chạy báo cáo phân tích trực tiếp trên hệ thống OLTP. Đây là lỗi phổ biến nhất và nguy hiểm nhất, như tình huống mở đầu. Luôn tách tải phân tích sang một hệ thống riêng.

Lỗi 2 — Không định nghĩa grain rõ ràng. Nếu các thành viên trong nhóm hiểu grain khác nhau (người nghĩ "một hoá đơn", người nghĩ "một dòng hàng"), bạn sẽ có những con số tổng hợp sai mà rất khó phát hiện. Hãy viết grain thành một câu và dán lên đầu tài liệu thiết kế.

Lỗi 3 — Trộn nhiều grain vào một fact table. Đừng để một bảng vừa có dòng ở mức hoá đơn vừa có dòng ở mức dòng hàng. Khi SUM lên bạn sẽ bị tính trùng (double counting).

Lỗi 4 — Chuẩn hoá dimension quá mức. Nhiều BA quen tư duy 3NF nên phản xạ tách dimension ra nhiều bảng. Trong kho dữ liệu, phi chuẩn hoá dimension là đúng đắn có chủ đích, không phải lỗi thiết kế.

Lỗi 5 — Ghi đè dimension khi giá trị thay đổi. Như ví dụ ngân hàng, ghi đè làm mất lịch sử. Hãy cân nhắc SCD Type 2 cho những chiều mà lịch sử quan trọng.

Mẹo:

  • Luôn dùng surrogate key (số nguyên tự tăng) làm khoá chính của dimension, thay vì khoá nghiệp vụ. Điều này giúp xử lý SCD và bảo vệ kho khỏi thay đổi ở hệ thống nguồn.
  • Tạo một dòng "Unknown" trong mỗi dimension để xử lý dữ liệu thiếu khoá, tránh mất bản ghi fact khi JOIN.
  • Với câu hỏi "nên star hay snowflake", mặc định chọn star vì sự đơn giản và tốc độ; chỉ snowflake khi có lý do rõ ràng.

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

Hãy thực hành với bối cảnh một chuỗi rạp chiếu phim giả định tại Việt Nam (kiểu CGV). Doanh nghiệp muốn phân tích doanh thu bán vé.

  • Phân biệt OLTP/OLAP: Liệt kê 3 câu hỏi mà hệ thống bán vé tại quầy (OLTP) cần trả lời, và 3 câu hỏi mà ban lãnh đạo (OLAP) cần trả lời. Chỉ ra vì sao loại thứ hai không nên chạy trên hệ thống quầy.
  • Thiết kế star schema: Áp dụng bốn bước Kimball. Xác định business process, viết một câu định nghĩa grain, liệt kê tối thiểu 4 dimension (gợi ý: thời gian, phim, rạp, khách hàng/loại vé) và 3 measure cho fact table fact_ticket_sales.
  • Phân loại measure: Trong các số đo bạn chọn, đâu là additive, đâu là semi-additive hoặc non-additive? Giải thích.
  • Tình huống SCD: Một rạp được nâng cấp từ hạng "Standard" lên "IMAX" giữa năm. Bạn sẽ xử lý chiều dim_theater theo SCD Type nào, và vì sao? Mô tả các cột bạn cần thêm.
  • Phản biện: Một đồng nghiệp đề xuất tách dim_movie thành 3 bảng (phim → thể loại → nhà phát hành) cho "gọn". Hãy viết một đoạn ngắn lập luận nên giữ star hay chuyển snowflake trong trường hợp này.
Hãy vẽ sơ đồ hình sao của bạn trên giấy hoặc bằng công cụ ERD trước khi đối chiếu với phần tóm tắt.

Tóm tắt

  • OLTP phục vụ vận hành: chuẩn hoá cao, ghi nhiều giao dịch nhỏ theo thời gian thực. OLAP phục vụ phân tích: phi chuẩn hoá, đọc và tổng hợp khối lượng lớn dữ liệu lịch sử. Đừng ép một hệ thống làm cả hai.
  • Data Warehouse là kho dữ liệu tập trung, hướng chủ đề, tích hợp, biến thiên theo thời gian và không biến động — được nạp qua quy trình ETL.
  • Star Schema gồm một fact table trung tâm (chứa measure ở một grain xác định) và các dimension table phẳng bao quanh (chứa ngữ cảnh để lát cắt). Đây là mô hình nền tảng của thiết kế phân tích.
  • Quy trình thiết kế bốn bước của Kimball: chọn business process → xác định grain → chọn dimension → chọn measure.
  • Ghi nhớ các kỹ thuật then chốt: surrogate key, SCD Type 2 để lưu lịch sử dimension, phân biệt measure additive/semi-additive/non-additive, và mặc định ưu tiên star hơn snowflake.
Nắm vững bài này, bạn đã có nền tảng để bước sang các chủ đề nâng cao như reporting database tách biệt OLTP, và để tự tin tham gia thiết kế hệ thống BI thực tế cho doanh nghiệp.