Chuẩn hóa dữ liệu trong việc tạo Database

Chuẩn hóa dữ liệu trong việc tạo Database

Cách xử lý các vấn đề xoay quanh việc tạo database sao cho hợp lý va tối ưu luôn là bài toán mà các back-end Dev luôn suy nghĩ. Việc bỏ qua các kiến thức về "cấu trúc dữ liệu và giải thuật " (Data Structure & Algorithms) sẽ khiến cho việc lưu trữ dữ liệu để có thể sử dụng một cách hiệu quả trở nên khó khăn. Tuy nhiên, một số bài toán thực tế lại phải bỏ qua hay hạn chế các quy tắc trong việc cấu trúc dữ liệu. Chẳng hạn như :

Ta có 3 bảng (demo)

image (1).png

image.png

image (2).png

Với một hóa đơn mà đặt nhiều sản phẩm có cùng product_id, không phải cứ lặp lại product_id trong bảng Orderdetail mà mình phải tăng lên số lượng (tất nhiên). Nhưng sinh ra 1 vấn đề : đó là khi sản phẩm thay đổi về giá, giá trị của hóa đơn lại thay đổi (do việc nối các bảng nhau) gây khó khăn cho việc kiểm toán. Nên mình sẽ lưu thêm vào Orderdetail một cột nữa đó là cột DetailPrice (giá tại thời điểm đó).

image (3).png

Điều này giúp tránh ảnh hưởng đến các hóa đơn trước khi có sự thay đổi về giá của 1 sản phẩm nào đó. Nhưng điều này lại sai về việc chuẩn hóa. Vì theo logic, giá có thể lấy được từ mã sản phẩm (product_id). Có điều, bài toán ở đây liên quan đến vấn đề thời gian và 1 sản phẩm có thể có nhiều giá. Và vì vậy mà ta vẫn có một cách giải quyết khác là tách thêm 1 bảng liên quan đến sản phẩm và giá.

Tiếp theo, khi mà mình muốn tính tổng tiền cho một hóa đơn thì phải lấy giá từ Orderdetail (DetailPrice x quantity) rồi cộng hết theo mã hóa đơn để ra được tổng tiền. Và khi mỗi lần truy cập vào bảng Order lại phải chạy lại phép tính trên. Điều này làm giảm hiệu suất đáng kể, trong khi tổng tiền của hóa đơn lại không bao giờ thay đổi nên việc lưu lại tổng tiền trên bảng Order cũng là một điều cần thiết.

image (4).png

Điều này cũng vi phạm quy tắc của chuẩn hóa khi mà lưu lại 1 cột có thể tính từ 1 bảng khác nhưng lại rất phù hợp với bài toán thực tế khi mà mình chỉ muốn xem lại tổng tiền của hóa đơn mà không cần phải tính toán lại hay động vào Orderdetail.

Ở bảng Order, ta có cột Customer_id được nối với bảng Customers :

image (5).png

Khi dựa vào cột Customer_id ở `Order` để có thể lấy được thông tin của khách hàng (ở đây là tên chẳng hạn) thì đôi khi ta sẽ Join 2 bảng lại với nhau (2 bảng lớn). Điều này khá là nặng mặc dù đã có limit. Từ đó có khái niệm về "flat table", đại khái là lưu luôn thằng customer_name ở bảng Order luôn (vì hầu như sẽ không bao giờ thay đổi về tên khách hàng của hóa đơn đó):

image (6).png

Về sau khi muốn lấy thông tin khách hàng đã đặt thì mình lấy từ chính bảng Order chứ không nối sang bảng Customers nữa.

Suy cho cùng, trên thực tế không có khái niệm nào là "chuẩn" về Database cả, phải tinh chỉnh sao cho phù hợp với bài toán thực tế.