Mở đầu — vì sao bài này quan trọng
Ở Bài 9, chúng ta đã vẽ Conceptual Data Model — bức tranh tổng quan, cấp cao, dùng để nói chuyện với lãnh đạo và khách hàng. Nó trả lời câu hỏi "doanh nghiệp quan tâm đến những cái gì?" bằng vài chục entity và những đường nối thô. Nhưng nếu bạn đưa bản vẽ đó cho một kỹ sư database và bảo họ tạo bảng, họ sẽ lúng túng: Khóa chính là gì? Trường nào bắt buộc? Một khách hàng có thể có bao nhiêu đơn hàng? Quan hệ nhiều-nhiều giải quyết ra sao?
Logical Data Model (LDM) chính là cây cầu nối giữa hai thế giới đó. Đây là tầng mô hình mà người làm phân tích nghiệp vụ (BA) phải làm chủ, bởi vì nó vừa đủ chi tiết để chính xác về mặt kỹ thuật, lại vừa độc lập với công nghệ để không bị khóa cứng vào một hệ quản trị cơ sở dữ liệu (DBMS) cụ thể. Nói cách khác: LDM mô tả dữ liệu phải như thế nào trên lý thuyết, trước khi ai đó quyết định nó sẽ chạy trên MySQL, PostgreSQL hay SQL Server.
Tôi đã chứng kiến nhiều dự án ở Việt Nam "nhảy cóc" từ conceptual thẳng xuống code SQL, bỏ qua tầng logical. Hậu quả là dữ liệu trùng lặp tràn lan, sửa một chỗ sót mười chỗ, báo cáo sai số liệu. LDM được làm nghiêm túc sẽ giúp bạn tránh đúng những cái bẫy đó. Đây là bản thiết kế chi tiết — "bản vẽ kết cấu" — mà cả nghiệp vụ lẫn kỹ thuật đều soi vào và đồng thuận.
Khái niệm cốt lõi
Logical Data Model là mô hình mô tả đầy đủ và chi tiết dữ liệu nghiệp vụ, đã được chuẩn hóa (normalized), nhưng không phụ thuộc vào DBMS cụ thể. Một LDM hoàn chỉnh phải có đủ năm thành phần dưới đây.
1. Tất cả các entity (đầy đủ, không thiếu)
Conceptual model thường chỉ giữ các entity "nghiệp vụ nhìn thấy được" như Khách hàng, Sản phẩm, Đơn hàng. Sang LDM, bạn phải bổ sung cả những entity ẩn mà nghiệp vụ không gọi tên nhưng dữ liệu bắt buộc phải có — điển hình là bảng trung gian (associative/junction entity) để hóa giải quan hệ nhiều-nhiều. Ví dụ "Đơn hàng" và "Sản phẩm" có quan hệ nhiều-nhiều, ở LDM sẽ xuất hiện entity mới ChiTietDonHang mà ở conceptual chưa hề tồn tại.
2. Tất cả các attribute
Mỗi entity được liệt kê đầy đủ thuộc tính: tên rõ ràng, ý nghĩa, kiểu dữ liệu logic (chứ chưa phải kiểu vật lý). Lưu ý cụm từ "kiểu logic": ở LDM ta nói "số nguyên", "chuỗi văn bản", "ngày", "số tiền" — chứ chưa nói INT(11), VARCHAR(255) hay DECIMAL(15,2). Việc ánh xạ sang kiểu vật lý cụ thể là việc của Physical Data Model (Bài 11). Tách bạch như vậy giúp model dùng được cho nhiều nền tảng.
3. Primary Key và Foreign Key
Mỗi entity phải có khóa chính (Primary Key) xác định duy nhất từng dòng. Mỗi quan hệ được hiện thực bằng khóa ngoại (Foreign Key) — con khóa của entity "cha" được đặt vào entity "con". Đây là điểm khác biệt lớn so với conceptual model: ở conceptual, quan hệ chỉ là một đường kẻ; ở logical, quan hệ trở thành một cột FK cụ thể, có thể chỉ ra chính xác.
4. Cardinality (lực lượng quan hệ)
LDM phải nói rõ một entity liên hệ với entity khác theo tỷ lệ nào: một-một, một-nhiều, nhiều-nhiều, và có bắt buộc hay không (optional/mandatory). "Một khách hàng có thể có nhiều đơn hàng (kể cả 0)" khác hẳn "Mỗi đơn hàng bắt buộc thuộc về đúng một khách hàng". Notation thường dùng là Crow's Foot (chúng ta đã học ở Bài 8).
5. Áp dụng chuẩn hóa (Normalization)
Đây là linh hồn của LDM. Mô hình logic chuẩn mực phải đạt tối thiểu dạng chuẩn 3 (3NF): không lặp nhóm dữ liệu, không phụ thuộc bộ phận, không phụ thuộc bắc cầu. Chi tiết kỹ thuật của 1NF, 2NF, 3NF sẽ được mổ xẻ ở Bài 12–14; ở đây bạn chỉ cần nắm nguyên tắc: mỗi dữ kiện chỉ được lưu đúng một nơi. Nhờ đó LDM loại bỏ trùng lặp và mâu thuẫn dữ liệu ngay từ khâu thiết kế.
LDM nằm ở đâu trong ba tầng?
| Tiêu chí | Conceptual | Logical | Physical |
|---|---|---|---|
| Đối tượng đọc | Lãnh đạo, khách hàng | BA, Data Architect | DBA, lập trình viên |
| Mức chi tiết | Entity chính | Đủ entity + attribute + key | Cột, kiểu vật lý, index |
| Phụ thuộc DBMS | Không | Không | Có (MySQL/Postgres...) |
| Chuẩn hóa | Chưa | Đã (3NF) | Có thể denormalize |
Tình huống thực tế
Ví dụ 1 — Tiki và bài toán đơn hàng nhiều sản phẩm
Giả sử nhóm BA tại một sàn thương mại điện tử kiểu Tiki phác conceptual model gồm ba entity: KhachHang, DonHang, SanPham. Lãnh đạo gật đầu vì nó dễ hiểu. Nhưng khi xuống LDM, vấn đề lộ ra: một đơn hàng chứa nhiều sản phẩm, và một sản phẩm xuất hiện trong nhiều đơn — đây là quan hệ nhiều-nhiều, không thể hiện thực trực tiếp bằng FK.
Nhóm BA buộc phải sinh ra một entity trung gian ChiTietDonHang với khóa chính kép (MaDonHang, MaSanPham), kèm các thuộc tính riêng của dòng: SoLuong, DonGiaTaiThoiDiemMua. Chính cái thuộc tính cuối cùng dạy cho cả nhóm một bài học quý: giá bán phải được "đóng băng" tại thời điểm đặt hàng, chứ không tham chiếu live tới SanPham.GiaHienTai. Nếu không, khi shop tăng giá tháng sau, toàn bộ hóa đơn cũ sẽ tự động sai lệch.
Bài học: LDM bắt bạn đối diện với quan hệ nhiều-nhiều và bản chất "ảnh chụp" của dữ liệu giao dịch — những thứ conceptual model che giấu.
Ví dụ 2 — Phòng khám tư và lỗi phụ thuộc bắc cầu
Một chuỗi phòng khám tư ở TP.HCM thuê đội phát triển làm hệ thống lịch hẹn. Bản nháp ban đầu của bảng LichHen chứa: MaLichHen, MaBacSi, TenBacSi, ChuyenKhoa, MaBenhNhan, TenBenhNhan, NgayHen. Nhìn thì gọn, dùng được ngay. Nhưng khi áp chuẩn hóa cho LDM, BA phát hiện TenBacSi và ChuyenKhoa phụ thuộc vào MaBacSi chứ không phụ thuộc vào MaLichHen — đây là phụ thuộc bắc cầu, vi phạm 3NF.
Hậu quả thực tế nếu để nguyên: một bác sĩ chuyển chuyên khoa hoặc đổi tên (sau khi cưới chẳng hạn), nhân viên phải sửa tay hàng nghìn dòng lịch hẹn cũ; chỉ cần sót vài dòng là dữ liệu mâu thuẫn. LDM chuẩn tách thành ba entity: BacSi (MaBacSi, TenBacSi, MaChuyenKhoa), BenhNhan (MaBenhNhan, TenBenhNhan), và LichHen chỉ giữ các FK MaBacSi, MaBenhNhan cùng NgayHen. Từ đó, tên bác sĩ chỉ tồn tại đúng một nơi.
Bài học: LDM không chỉ "vẽ đẹp" mà còn buộc bạn truy ra những phụ thuộc dữ liệu ẩn, ngăn lỗi cập nhật về sau.
Ví dụ 3 — Ngân hàng VPBank và sự độc lập công nghệ
Một dự án thẻ tín dụng tại ngân hàng kiểu VPBank ban đầu định dùng Oracle. Đội BA xây dựng LDM đầy đủ: các entity KhachHang, TaiKhoan, The, GiaoDich, với khóa, FK, cardinality và đã chuẩn hóa 3NF — nhưng cố ý không ghi bất kỳ kiểu dữ liệu Oracle nào (không NUMBER, không VARCHAR2). Sáu tháng sau, vì lý do chi phí license, ban lãnh đạo quyết định chuyển sang PostgreSQL.
Vì LDM được giữ độc lập DBMS, đội ngũ không phải vẽ lại toàn bộ mô hình. Họ chỉ cần làm lại bước ánh xạ sang Physical Model: NUMBER(15,2) của Oracle đổi thành NUMERIC(15,2) của Postgres, kiểu ngày Oracle đổi sang TIMESTAMP. Cấu trúc nghiệp vụ — entity nào, quan hệ ra sao — giữ nguyên vẹn. Tài liệu LDM trở thành "nguồn chân lý" mà cả hai phương án công nghệ đều bám vào.
Bài học: Chính vì LDM không dính vào DBMS nên nó là tài sản bền vững, sống lâu hơn cả quyết định chọn công nghệ.
Hướng dẫn từng bước
Để chuyển từ Conceptual Model lên một Logical Data Model hoàn chỉnh, hãy đi theo bảy bước sau.
- Kế thừa entity từ conceptual model. Liệt kê lại toàn bộ entity nghiệp vụ đã thống nhất ở Bài 9. Đây là điểm xuất phát, đừng tự ý thêm bớt vội.
- Bổ sung đầy đủ attribute cho từng entity. Với mỗi entity, hỏi: "Nghiệp vụ cần lưu những thông tin gì?" Gán tên rõ ràng và kiểu logic (số, chuỗi, ngày, boolean, số tiền). Chưa cần độ dài hay kiểu vật lý.
- Xác định Primary Key cho mỗi entity. Chọn thuộc tính (hoặc tổ hợp thuộc tính) định danh duy nhất từng dòng. Nếu không có khóa tự nhiên tốt, dùng khóa thay thế (surrogate key) — chủ đề này được bàn kỹ ở Bài 6.
- Vẽ các quan hệ và đặt khóa ngoại. Với mỗi quan hệ, xác định bên "một" và bên "nhiều", rồi đặt FK vào bên "nhiều". Gặp quan hệ nhiều-nhiều thì dừng lại tạo bảng trung gian với khóa kép.
- Ghi rõ cardinality và tính bắt buộc. Dùng Crow's Foot để chỉ rõ 0..1, 1, 0..nhiều, 1..nhiều cho cả hai đầu quan hệ. Đây là lúc làm rõ "có thể không có" hay "bắt buộc phải có".
- Áp dụng chuẩn hóa đến 3NF. Soi từng entity: có nhóm lặp không (1NF)? Có thuộc tính chỉ phụ thuộc một phần khóa kép không (2NF)? Có phụ thuộc bắc cầu không (3NF)? Tách bảng cho đến khi sạch.
- Rà soát cùng nghiệp vụ và đặt tên nhất quán. Trình bày lại LDM cho người dùng nghiệp vụ xác nhận ý nghĩa, đồng thời thống nhất quy ước đặt tên (ví dụ: tiền tố
Macho khóa, danh từ số ít cho entity).
Lỗi thường gặp & mẹo
Lỗi 1 — Đưa kiểu dữ liệu vật lý vào quá sớm. Rất nhiều BA viết ngay VARCHAR(255), BIGINT vào LDM. Làm vậy là trộn lẫn tầng logical và physical, khiến model bị khóa vào một DBMS. Mẹo: ở LDM chỉ ghi "chuỗi văn bản", "số nguyên"; để dành chi tiết vật lý cho Bài 11.
Lỗi 2 — Bỏ quên bảng trung gian cho quan hệ nhiều-nhiều. Đây là lỗi phổ biến nhất. Hai entity nối nhau bằng đường nhiều-nhiều mà không có entity trung gian là dấu hiệu LDM chưa hoàn chỉnh. Mẹo: cứ thấy nhiều-nhiều là phản xạ tạo junction entity ngay.
Lỗi 3 — "Chuẩn hóa quá tay" hoặc lười chuẩn hóa. Có người tách bảng đến mức một truy vấn phải join cả chục bảng; ngược lại có người để nguyên dữ liệu trùng lặp cho "tiện". Mẹo: LDM nên đạt 3NF làm chuẩn — sạch và cân bằng. Việc cố ý gộp lại để tối ưu tốc độ (denormalization) là quyết định của tầng physical, có chủ đích, sẽ học ở Bài 15.
Lỗi 4 — Đặt tên mơ hồ, không nhất quán. KH, khach_hang, Customer lẫn lộn trong cùng một model gây rối loạn. Mẹo: thống nhất một quy ước đặt tên ngay từ đầu và ghi vào Data Dictionary (Bài 17).
Lỗi 5 — Quên đánh dấu thuộc tính bắt buộc/tùy chọn. Không chỉ rõ trường nào null được sẽ gây tranh cãi khi lập trình. Mẹo: trong LDM, đánh dấu rõ mandatory/optional cho mỗi attribute quan trọng.
Mẹo tổng: Hãy coi LDM là tài liệu "ai đọc cũng hiểu giống nhau". Nếu một lập trình viên và một người nghiệp vụ nhìn vào mà rút ra hai cách hiểu khác nhau, LDM của bạn còn thiếu chi tiết.
Bài tập thực hành
Một trung tâm tiếng Anh tại Đà Nẵng cần hệ thống quản lý lớp học. Thông tin nghiệp vụ thu thập được:
- Mỗi học viên có họ tên, số điện thoại, email.
- Mỗi lớp học có tên lớp, trình độ, học phí, được dạy bởi đúng một giáo viên.
- Mỗi giáo viên có họ tên, chuyên môn; một giáo viên có thể dạy nhiều lớp.
- Một học viên có thể đăng ký nhiều lớp, và một lớp có nhiều học viên. Khi đăng ký cần lưu ngày đăng ký và trạng thái thanh toán.
- Liệt kê tất cả entity cần có trong Logical Data Model (gợi ý: có một entity "ẩn" mà mô tả nghiệp vụ không gọi tên trực tiếp).
- Với mỗi entity, ghi các attribute kèm kiểu logic và xác định Primary Key.
- Đặt các Foreign Key đúng chỗ; chỉ ra bạn xử lý quan hệ nhiều-nhiều giữa Học viên và Lớp học như thế nào.
- Ghi cardinality cho từng quan hệ (dùng cách diễn đạt một-nhiều / nhiều-nhiều và bắt buộc/tùy chọn).
- Kiểm tra: model của bạn đã đạt 3NF chưa? Thuộc tính
học phínên nằm ở entity nào, vàhọc phí thực thu của từng học viên(nếu có giảm giá) nên đặt ở đâu?
tên giáo viên nằm trong entity LopHoc, hãy tự hỏi nó phụ thuộc vào khóa nào — đó chính là bài kiểm tra 3NF.Tóm tắt
Logical Data Model là tầng mô hình chi tiết, đầy đủ và đã chuẩn hóa của dữ liệu nghiệp vụ, nhưng vẫn độc lập với hệ quản trị cơ sở dữ liệu. Một LDM hoàn chỉnh gồm: tất cả entity (kể cả bảng trung gian), tất cả attribute với kiểu logic, Primary Key và Foreign Key, cardinality rõ ràng, và chuẩn hóa đến tối thiểu 3NF.
Khác với Conceptual Model vốn dành cho lãnh đạo và chỉ vẽ bức tranh lớn, LDM là bản thiết kế kỹ thuật để BA và Data Architect làm việc; khác với Physical Model vốn gắn chặt vào MySQL hay PostgreSQL, LDM cố ý không dính kiểu dữ liệu vật lý để sống lâu hơn mọi quyết định công nghệ. Ba câu chuyện — đơn hàng nhiều-nhiều của sàn TMĐT, phụ thuộc bắc cầu của phòng khám, và sự độc lập công nghệ của ngân hàng — cho thấy LDM không phải thủ tục giấy tờ mà là nơi bạn phát hiện và ngăn chặn lỗi dữ liệu ngay từ thiết kế.
Ở các bài tiếp theo, bạn sẽ học cách hiện thực LDM thành Physical Model (Bài 11) và đào sâu từng bậc chuẩn hóa 1NF–3NF (Bài 12–14). Hãy nắm chắc tầng logical trước — vì mọi bảng SQL tốt đều bắt đầu từ một mô hình logic sạch.