Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn là BA (Business Analyst) trong một dự án xây dựng hệ thống quản lý đơn hàng cho một chuỗi cà phê có 80 cửa hàng tại TP.HCM và Hà Nội. Dev đưa cho bạn một bảng Excel "tạm" để lưu đơn hàng: mỗi dòng có tên khách, số điện thoại, địa chỉ giao, tên sản phẩm, giá, tên cửa hàng, địa chỉ cửa hàng, tên nhân viên giao. Mọi thứ trông gọn gàng cho đến ngày một cửa hàng đổi địa chỉ. Bộ phận vận hành phải sửa hàng nghìn dòng dữ liệu cũ, và họ chỉ sửa được 90%. Phần còn lại sai địa chỉ, dẫn đến báo cáo doanh thu theo khu vực bị lệch.
Đó chính xác là cái giá của một mô hình dữ liệu chưa được chuẩn hóa (normalization). Bài học này dạy bạn hai kỹ năng cốt lõi mà bất kỳ BA làm việc với dữ liệu nào cũng phải nắm: chuẩn hóa dữ liệu để loại bỏ dư thừa và đảm bảo toàn vẹn, và xây dựng Data Dictionary (từ điển dữ liệu) để tài liệu hóa từng trường dữ liệu một cách rõ ràng cho cả đội phát triển lẫn nghiệp vụ.
Đây không phải kiến thức "chỉ dành cho dev". Là BA, bạn là người đứng giữa nghiệp vụ và kỹ thuật. Khi bạn hiểu chuẩn hóa, bạn phát hiện được những lỗi thiết kế ngay từ giai đoạn phân tích — trước khi chúng trở thành nợ kỹ thuật tốn kém. Khi bạn biết viết Data Dictionary, bạn tạo ra "ngôn ngữ chung" giúp cả dự án hiểu đúng từng con số.
Khái niệm cốt lõi
Chuẩn hóa là gì và tại sao cần làm
Normalization (chuẩn hóa) là quá trình tổ chức dữ liệu trong cơ sở dữ liệu thành các bảng có cấu trúc hợp lý, nhằm ba mục tiêu:
- Giảm dư thừa dữ liệu (data redundancy): không lưu cùng một thông tin ở nhiều nơi. Địa chỉ một cửa hàng chỉ nên tồn tại đúng một chỗ.
- Ngăn các bất thường khi cập nhật (anomalies): tránh tình huống sửa một chỗ mà quên chỗ khác.
- Đảm bảo toàn vẹn dữ liệu (data integrity): dữ liệu luôn nhất quán, không mâu thuẫn với chính nó.
- Update anomaly (bất thường khi sửa): khi một thông tin bị lặp lại ở nhiều dòng, sửa một dòng mà sót dòng khác sẽ tạo ra dữ liệu mâu thuẫn. Ví dụ cửa hàng đổi địa chỉ như câu chuyện mở đầu.
- Insertion anomaly (bất thường khi thêm): bạn không thể thêm một thực thể mới nếu thiếu một thực thể liên quan. Ví dụ: nếu bảng gộp chung "sản phẩm" và "đơn hàng", bạn không thể thêm một sản phẩm mới vào danh mục cho đến khi có ít nhất một đơn hàng chứa nó.
- Deletion anomaly (bất thường khi xóa): xóa một dòng vô tình làm mất luôn thông tin khác. Ví dụ: xóa đơn hàng cuối cùng của một khách hàng lại làm mất luôn thông tin liên hệ của khách đó.
Khái niệm nền tảng: phụ thuộc hàm
Trước khi đi vào các dạng chuẩn, bạn cần hiểu functional dependency (phụ thuộc hàm). Nói đơn giản: thuộc tính B phụ thuộc hàm vào thuộc tính A nếu cứ biết giá trị của A là xác định được duy nhất giá trị của B. Ta viết A → B.
Ví dụ: Mã_sản_phẩm → Tên_sản_phẩm. Biết mã SKU là biết chính xác tên sản phẩm. Ngược lại, Tên_sản_phẩm → Mã_sản_phẩm chưa chắc đúng nếu có hai sản phẩm trùng tên. Hiểu phụ thuộc hàm chính là chìa khóa để nhận ra dữ liệu nào nên tách ra bảng riêng.
Các dạng chuẩn
Chuẩn hóa diễn ra theo từng bậc, gọi là Normal Forms (dạng chuẩn). Trong bài tổng quan này, chúng ta nắm bản chất và động cơ của ba dạng chuẩn đầu — vốn chiếm 95% nhu cầu thực tế. (Chi tiết kỹ thuật từng dạng sẽ được mổ xẻ sâu hơn ở các bài sau trong khóa.)
1NF — First Normal Form (dạng chuẩn 1): Mỗi ô chỉ chứa một giá trị nguyên tử (atomic), không chứa danh sách hay nhóm lặp. Mỗi dòng phải định danh được bằng khóa chính. Ví dụ vi phạm 1NF: một ô "Số điện thoại" chứa 0901234567, 0912345678. Cần tách ra để mỗi số là một dòng/một ô riêng.
2NF — Second Normal Form (dạng chuẩn 2): Đạt 1NF, và mọi thuộc tính không khóa phải phụ thuộc vào toàn bộ khóa chính, chứ không chỉ một phần. Dạng này chỉ phát sinh vấn đề khi khóa chính là composite key (khóa phức hợp) gồm nhiều cột. Ví dụ: bảng chi tiết đơn hàng có khóa (Mã_đơn, Mã_sản_phẩm), nhưng cột Tên_sản_phẩm chỉ phụ thuộc vào Mã_sản_phẩm — đó là partial dependency (phụ thuộc một phần), cần tách ra.
3NF — Third Normal Form (dạng chuẩn 3): Đạt 2NF, và không có thuộc tính không khóa nào phụ thuộc vào một thuộc tính không khóa khác (gọi là transitive dependency — phụ thuộc bắc cầu). Ví dụ: bảng nhân viên có Mã_NV → Mã_phòng → Tên_phòng. Tên_phòng phụ thuộc vào Mã_phòng chứ không trực tiếp vào Mã_NV, nên cần tách bảng Phòng ra riêng.
Một câu thần chú dễ nhớ cho 3NF (do nhà nghiên cứu Bill Kent diễn đạt): "Mỗi thuộc tính không khóa phải phụ thuộc vào khóa, toàn bộ khóa, và không gì khác ngoài khóa."
Data Dictionary là gì
Data Dictionary (từ điển dữ liệu) là tài liệu mô tả có cấu trúc về từng phần tử dữ liệu trong hệ thống. Với mỗi thuộc tính (attribute), từ điển dữ liệu thường ghi:
- Tên trường (tên kỹ thuật và tên nghiệp vụ).
- Mô tả nghiệp vụ: trường này nghĩa là gì với người dùng.
- Kiểu dữ liệu và độ dài (ví dụ
VARCHAR(50),DECIMAL(15,2)). - Ràng buộc (constraints): NOT NULL, UNIQUE, khóa chính/khóa ngoại, miền giá trị hợp lệ.
- Giá trị mặc định và ví dụ mẫu.
- Quy tắc nghiệp vụ liên quan (ví dụ: số tiền không âm).
- Nguồn dữ liệu và người sở hữu (data owner).
Tình huống thực tế
Tình huống 1 — Tiki và bài toán cập nhật giá nhà cung cấp
Giả định một sàn TMĐT như Tiki ban đầu lưu thông tin nhà cung cấp ngay trong bảng sản phẩm: mỗi sản phẩm có thêm cột Tên_nhà_cung_cấp, Email_NCC, Hotline_NCC. Một NCC như "Công ty Mỹ phẩm ABC" cung cấp 1.200 mã sản phẩm — nghĩa là email và hotline của họ bị lặp lại 1.200 lần.
Khi ABC đổi hotline chăm sóc, đội vận hành phải UPDATE 1.200 dòng. Một lần chạy lệnh bị gián đoạn giữa chừng khiến 300 dòng còn hotline cũ. Hệ quả: hệ thống gửi thông báo đến hai số khác nhau cho cùng một NCC — đây chính là update anomaly.
Bài học: Tách Nhà_cung_cấp thành bảng riêng với khóa Mã_NCC, rồi bảng sản phẩm chỉ giữ Mã_NCC làm khóa ngoại. Khi đó đổi hotline chỉ cần sửa một dòng. Đây là ứng dụng trực tiếp của 3NF — loại bỏ phụ thuộc bắc cầu Mã_SP → Mã_NCC → Hotline_NCC.
Tình huống 2 — Phòng khám tư và deletion anomaly
Một phòng khám tư ở Đà Nẵng dùng một bảng duy nhất Lượt_khám chứa cả thông tin bệnh nhân: Mã_bệnh_nhân, Họ_tên, Năm_sinh, Bảo_hiểm, cùng Ngày_khám, Chẩn_đoán. Một bệnh nhân mới đến đăng ký nhưng chưa khám — họ không thể nhập vào hệ thống vì chưa có lượt khám nào (insertion anomaly). Ngược lại, khi nhân viên dọn dữ liệu cũ và xóa lượt khám duy nhất của một bệnh nhân, toàn bộ thông tin bệnh nhân đó biến mất (deletion anomaly).
Bài học: Tách thành Bệnh_nhân và Lượt_khám riêng, liên kết qua Mã_bệnh_nhân. Thông tin bệnh nhân tồn tại độc lập với lượt khám. Đây là lý do vì sao chuẩn hóa không chỉ là chuyện kỹ thuật — nó phản ánh đúng bản chất nghiệp vụ: bệnh nhân và lượt khám là hai thực thể độc lập.
Tình huống 3 — Data Dictionary cứu một dự án ngân hàng
Một dự án core banking tại một ngân hàng Việt có trường so_du (số dư). Đội backend hiểu đây là số dư khả dụng, đội báo cáo hiểu là số dư cuối ngày, còn đội nghiệp vụ hiểu là số dư đã trừ phong tỏa. Trong ba tháng, các báo cáo lệch nhau và không ai biết vì sao.
Khi BA vào cuộc, việc đầu tiên là dựng Data Dictionary: ghi rõ so_du_kha_dung (DECIMAL(18,2), NOT NULL, đơn vị VND, = số dư sổ cái trừ số tiền bị phong tỏa, cập nhật real-time) và so_du_cuoi_ngay (chốt lúc 18:00 mỗi ngày làm việc). Chỉ một bảng từ điển rõ ràng đã chấm dứt ba tháng tranh cãi.
Bài học: Data Dictionary không phải thủ tục giấy tờ — nó là công cụ phòng ngừa hiểu lầm tốn kém. Một dòng định nghĩa rõ ràng có thể tiết kiệm hàng tuần làm lại báo cáo.
Hướng dẫn từng bước
Đây là quy trình thực hành bạn có thể áp dụng cho bất kỳ tập dữ liệu nào.
Bước 1 — Thu thập dữ liệu thô. Lấy mẫu thật: một file Excel, một màn hình nhập liệu, một báo cáo hiện hành. Liệt kê tất cả các trường đang có.
Bước 2 — Đưa về 1NF. Tìm các ô chứa nhiều giá trị (danh sách số điện thoại, danh sách sản phẩm trong một ô) hoặc các nhóm cột lặp (SP1, SP2, SP3). Tách chúng thành từng dòng/từng bảng riêng để mỗi ô chỉ chứa một giá trị nguyên tử. Xác định khóa chính cho bảng.
Bước 3 — Xác định phụ thuộc hàm. Với mỗi cột, tự hỏi: "Cột này phụ thuộc vào cái gì để có giá trị duy nhất?" Vẽ ra các mũi tên A → B. Đây là bước quan trọng nhất.
Bước 4 — Đưa về 2NF. Nếu khóa chính gồm nhiều cột, tìm các thuộc tính chỉ phụ thuộc một phần khóa và tách chúng ra bảng riêng.
Bước 5 — Đưa về 3NF. Tìm các phụ thuộc bắc cầu (thuộc tính không khóa phụ thuộc thuộc tính không khóa khác) và tách ra. Sau bước này, mỗi bảng thường chỉ mô tả đúng một thực thể.
Bước 6 — Lập Data Dictionary. Với mỗi bảng kết quả, ghi lại từng cột: tên, mô tả nghiệp vụ, kiểu dữ liệu, ràng buộc, giá trị mẫu, quy tắc nghiệp vụ, người sở hữu. Dùng một bảng thống nhất cho toàn dự án.
Bước 7 — Rà soát cùng nghiệp vụ. Đưa cả mô hình đã chuẩn hóa và từ điển dữ liệu cho người dùng nghiệp vụ xác nhận. Họ sẽ phát hiện những định nghĩa sai mà bạn không thấy.
Một mẫu Data Dictionary tối thiểu trông như sau:
| Tên trường | Mô tả nghiệp vụ | Kiểu DL | Ràng buộc | Ví dụ |
|---|---|---|---|---|
| ma_khach_hang | Mã định danh khách hàng | VARCHAR(10) | PK, NOT NULL | KH000123 |
| ho_ten | Họ và tên đầy đủ | NVARCHAR(100) | NOT NULL | Nguyễn Văn An |
| so_dien_thoai | SĐT liên hệ chính | VARCHAR(15) | UNIQUE | 0901234567 |
| so_du_kha_dung | Số dư khả dụng (VND) | DECIMAL(18,2) | NOT NULL, >= 0 | 1500000.00 |
Lỗi thường gặp & mẹo
- Nhầm "ít bảng" là "thiết kế tốt". Người mới thường ngại tách bảng vì sợ phức tạp. Thực tế, gộp tất cả vào một bảng "cho gọn" mới là nguồn gốc của mọi anomaly. Đừng sợ có nhiều bảng — sợ dữ liệu mâu thuẫn mới đúng.
- Quá đà chuẩn hóa (over-normalization). Ngược lại, có người chia nhỏ đến mức truy vấn nào cũng phải JOIN hàng chục bảng, làm hệ thống chậm. Mục tiêu thực dụng cho hầu hết hệ thống nghiệp vụ là 3NF — đủ tốt cho đa số trường hợp. (Khi nào nên cố ý đi ngược lại — tức denormalization — sẽ là chủ đề riêng ở bài sau.)
- Bỏ qua phụ thuộc hàm, chỉ nhìn cảm tính. Luôn viết ra các mũi tên A → B. Khi có sơ đồ phụ thuộc rõ ràng, việc tách bảng trở nên cơ học chứ không còn mơ hồ.
- Data Dictionary viết một lần rồi bỏ. Từ điển dữ liệu phải là tài liệu sống, cập nhật mỗi khi schema đổi. Một từ điển lỗi thời còn nguy hiểm hơn không có, vì nó tạo niềm tin sai.
- Mẹo "một bảng — một ý nghĩa": sau khi chuẩn hóa, hãy đặt tên cho từng bảng bằng một danh từ số ít rõ nghĩa (Khách_hàng, Đơn_hàng, Sản_phẩm). Nếu bạn không gọi tên được bảng bằng một danh từ, nhiều khả năng bảng đó đang trộn lẫn nhiều thực thể và cần tách tiếp.
- Mẹo phát hiện anomaly nhanh: với mỗi bảng, tự hỏi ba câu — "Sửa một thông tin có phải sửa nhiều dòng không? Có thực thể nào không thêm được vì thiếu thực thể khác không? Xóa một dòng có làm mất thông tin không liên quan không?" Nếu "có" ở bất kỳ câu nào, bảng cần chuẩn hóa thêm.
Bài tập thực hành
Bài tập 1 — Nhận diện anomaly. Cho bảng Đăng_ký_khóa_học của một trung tâm tiếng Anh: (Mã_HV, Tên_HV, SĐT, Mã_lớp, Tên_lớp, Giảng_viên, SĐT_GV, Học_phí). Hãy chỉ ra ít nhất một update anomaly, một insertion anomaly và một deletion anomaly có thể xảy ra với thiết kế này.
Bài tập 2 — Vẽ phụ thuộc hàm. Với bảng ở Bài tập 1, hãy viết ra tất cả các phụ thuộc hàm bạn thấy (ví dụ Mã_HV → Tên_HV). Khóa chính nên là gì?
Bài tập 3 — Chuẩn hóa. Dựa trên sơ đồ phụ thuộc, tách bảng trên thành các bảng đạt 3NF. Liệt kê tên từng bảng, các cột, khóa chính và khóa ngoại.
Bài tập 4 — Lập Data Dictionary. Chọn một bảng kết quả từ Bài tập 3 và viết Data Dictionary đầy đủ cho nó (tên trường, mô tả nghiệp vụ, kiểu dữ liệu, ràng buộc, ví dụ). Cố gắng dùng kiểu dữ liệu hợp lý cho bối cảnh Việt Nam: dùng NVARCHAR cho tên tiếng Việt có dấu, DECIMAL cho học phí.
Gợi ý lời giải Bài tập 1: Update anomaly — đổi SĐT của một giảng viên phải sửa mọi dòng có giảng viên đó. Insertion anomaly — không thể tạo một lớp mới chưa có học viên nào đăng ký. Deletion anomaly — xóa học viên cuối cùng của một lớp làm mất thông tin lớp và giảng viên đó.
Tóm tắt
Trong bài này, bạn đã nắm hai trụ cột của công việc mô hình hóa dữ liệu dưới góc nhìn BA:
- Chuẩn hóa (normalization) giúp loại bỏ dư thừa, ngăn ba loại anomaly (update, insertion, deletion) và đảm bảo toàn vẹn dữ liệu. Công cụ tư duy cốt lõi là phụ thuộc hàm, và đích đến thực dụng cho hầu hết hệ thống nghiệp vụ là 3NF: mỗi thuộc tính không khóa phụ thuộc vào khóa, toàn bộ khóa, và không gì khác ngoài khóa.
- Data Dictionary (từ điển dữ liệu) tài liệu hóa từng trường — tên, ý nghĩa nghiệp vụ, kiểu, ràng buộc — tạo ra ngôn ngữ chung giữa nghiệp vụ và kỹ thuật, ngăn những hiểu lầm tốn kém như câu chuyện "số dư" ở ngân hàng.