Bạn có ít nhất năm tùy chọn này để mô hình hóa phân cấp loại bạn mô tả:
Kế thừa bảng đơn : một bảng cho tất cả các loại Sản phẩm, với đủ các cột để lưu trữ tất cả các thuộc tính của tất cả các loại. Điều này có nghĩa là rất nhiều cột, hầu hết trong số đó là NULL trên bất kỳ hàng nào.
Kế thừa bảng lớp : một bảng cho Sản phẩm, lưu trữ các thuộc tính chung cho tất cả các loại sản phẩm. Sau đó, một bảng cho mỗi loại sản phẩm, lưu trữ các thuộc tính cụ thể cho loại sản phẩm đó.
Kế thừa bảng bê tông : không có bảng cho các thuộc tính Sản phẩm phổ biến. Thay vào đó, một bảng cho mỗi loại sản phẩm, lưu trữ cả thuộc tính sản phẩm phổ biến và thuộc tính dành riêng cho sản phẩm.
LOB nối tiếp : Một bảng cho Sản phẩm, lưu trữ các thuộc tính chung cho tất cả các loại sản phẩm. Một cột thêm lưu trữ BLOB dữ liệu bán cấu trúc, theo định dạng XML, YAML, JSON hoặc một số định dạng khác. BLOB này cho phép bạn lưu trữ các thuộc tính cụ thể cho từng loại sản phẩm. Bạn có thể sử dụng Mẫu thiết kế lạ mắt để mô tả điều này, chẳng hạn như Mặt tiền và Memento. Nhưng bất kể bạn có một loạt các thuộc tính không thể truy vấn dễ dàng trong SQL; bạn phải tìm nạp toàn bộ blob trở lại ứng dụng và sắp xếp nó ra khỏi đó.
Thực thể-Thuộc tính-Giá trị : Một bảng cho Sản phẩm và một bảng xoay các thuộc tính cho các hàng, thay vì các cột. EAV không phải là một thiết kế hợp lệ đối với mô hình quan hệ, nhưng nhiều người vẫn sử dụng nó. Đây là "Mẫu thuộc tính" được đề cập bởi một câu trả lời khác. Xem các câu hỏi khác với thẻ eav trên StackOverflow để biết một số cạm bẫy.
Tôi đã viết thêm về điều này trong một bài thuyết trình, Mô hình dữ liệu mở rộng .
Những suy nghĩ bổ sung về EAV: Mặc dù nhiều người dường như ủng hộ EAV, nhưng tôi thì không. Nó có vẻ như là giải pháp linh hoạt nhất, và do đó là tốt nhất. Tuy nhiên, hãy ghi nhớ câu ngạn ngữ TANSTAAFL . Dưới đây là một số nhược điểm của EAV:
- Không có cách nào để tạo một cột bắt buộc (tương đương
NOT NULL
).
- Không có cách nào để sử dụng các kiểu dữ liệu SQL để xác nhận các mục.
- Không có cách nào để đảm bảo rằng tên thuộc tính được đánh vần nhất quán.
- Không có cách nào để đặt khóa ngoại vào các giá trị của bất kỳ thuộc tính đã cho nào, ví dụ: đối với bảng tra cứu.
- Tìm nạp kết quả trong bố cục dạng bảng thông thường rất phức tạp và tốn kém, vì để có được các thuộc tính từ nhiều hàng bạn cần thực hiện
JOIN
cho từng thuộc tính.
Mức độ linh hoạt mà EAV mang lại cho bạn đòi hỏi sự hy sinh trong các lĩnh vực khác, có thể làm cho mã của bạn phức tạp (hoặc tệ hơn) so với việc giải quyết vấn đề ban đầu theo cách thông thường hơn.
Và trong hầu hết các trường hợp, không cần thiết phải có mức độ linh hoạt đó. Trong câu hỏi của OP về các loại sản phẩm, việc tạo bảng cho mỗi loại sản phẩm cho các thuộc tính dành riêng cho sản phẩm sẽ đơn giản hơn rất nhiều, do đó bạn có một số cấu trúc nhất quán được thi hành ít nhất cho các mục cùng loại sản phẩm.
Tôi chỉ sử dụng EAV nếu mỗi hàng phải được phép có khả năng có một bộ thuộc tính riêng biệt. Khi bạn có một bộ các loại sản phẩm hữu hạn, EAV là quá mức cần thiết. Kế thừa bảng lớp sẽ là lựa chọn đầu tiên của tôi.
Cập nhật 2019: Tôi càng thấy mọi người sử dụng JSON như một giải pháp cho vấn đề "nhiều thuộc tính tùy chỉnh", tôi càng không thích giải pháp đó. Nó làm cho các truy vấn quá phức tạp, ngay cả khi sử dụng các hàm JSON đặc biệt để hỗ trợ chúng. Phải mất nhiều không gian lưu trữ hơn để lưu trữ tài liệu JSON, so với việc lưu trữ trong các hàng và cột thông thường.
Về cơ bản, không có giải pháp nào trong số này là dễ dàng hoặc hiệu quả trong cơ sở dữ liệu quan hệ. Toàn bộ ý tưởng về việc có "các thuộc tính biến đổi" về cơ bản là mâu thuẫn với lý thuyết quan hệ.
Những gì nó được đưa ra là bạn phải chọn một trong những giải pháp dựa trên đó là ít xấu nhất cho ứng dụng của bạn . Do đó, bạn cần biết bạn sẽ truy vấn dữ liệu như thế nào trước khi bạn chọn thiết kế cơ sở dữ liệu. Không có cách nào để chọn một giải pháp "tốt nhất" bởi vì bất kỳ giải pháp nào cũng có thể là tốt nhất cho một ứng dụng nhất định.