Tôi đang làm việc để cập nhật cơ sở dữ liệu sản phẩm của trang web của chúng tôi. Nó được xây dựng trong MySQL nhưng đây là một câu hỏi mẫu thiết kế cơ sở dữ liệu chung.
Tôi đang lên kế hoạch chuyển sang mô hình Supertype / Subtype. Cơ sở dữ liệu hiện tại / trước đây của chúng tôi chủ yếu là một bảng duy nhất có dữ liệu về một loại sản phẩm. Chúng tôi đang xem xét mở rộng cung cấp sản phẩm của chúng tôi để bao gồm các sản phẩm khác nhau.
Thiết kế dự thảo mới này là như thế này:
Product product_[type] product_attribute_[name]
---------------- ---------------- ----------------------------
part_number (PK) part_number (FK) attributeId (PK)
UPC specific_attr1 (FK) attribute_name
price specific_attr2 (FK)
... ...
Tôi có một câu hỏi liên quan đến các bảng thuộc tính sản phẩm. Ý tưởng ở đây là một sản phẩm có thể có một danh sách các thuộc tính nhất định như màu sắc: đỏ, xanh lá cây, xanh dương hoặc vật liệu: nhựa, gỗ, crôm, nhôm, v.v.
Danh sách này sẽ được lưu trữ trong một bảng và khóa chính (PK) cho mục thuộc tính đó sẽ được sử dụng trong bảng sản phẩm cụ thể làm khóa ngoại (FK).
(Cuốn sách Các mẫu kiến trúc ứng dụng doanh nghiệp của Martin Fowler gọi đây là " Ánh xạ khóa ngoài ")
Điều này cho phép giao diện trang web kéo danh sách các thuộc tính cho một loại thuộc tính nhất định và nhổ nó ra trong menu chọn thả xuống hoặc một số thành phần UI khác. Danh sách này có thể được coi là danh sách "được ủy quyền" của các giá trị thuộc tính.
Số lượng tham gia kết thúc xảy ra khi kéo một sản phẩm cụ thể xuất hiện quá mức đối với tôi. Bạn phải tham gia mọi bảng thuộc tính sản phẩm cho sản phẩm để bạn có thể nhận được các trường thuộc tính đó. Thông thường, trường đó có thể chỉ đơn giản là không có gì nhiều hơn một chuỗi (varchar) cho tên của nó.
Mẫu thiết kế này kết thúc việc tạo ra một số lượng lớn các bảng cũng như bạn kết thúc với một bảng cho mỗi thuộc tính. Một ý tưởng để chống lại điều này sẽ là tạo ra một cái gì đó nhiều hơn của một bảng lấy túi của Khăn cho tất cả các thuộc tính sản phẩm. Một cái gì đó như thế này:
product_attribute
----------------
attributeId (PK)
name
field_name
Bằng cách này, bảng của bạn có thể trông như thế này:
1 red color
2 blue color
3 chrome material
4 plastic material
5 yellow color
6 x-large size
Điều này có thể giúp giảm creep bảng nhưng nó không làm giảm số lượng tham gia và cảm thấy hơi sai khi kết hợp rất nhiều loại khác nhau vào một bảng. Nhưng bạn có thể dễ dàng có được tất cả các thuộc tính màu sắc có sẵn của Wap.
Tuy nhiên, có thể có một thuộc tính có nhiều trường hơn chỉ là "tên", chẳng hạn như giá trị RGB của màu. Điều này sẽ yêu cầu thuộc tính cụ thể đó có thể có một bảng khác hoặc có một trường duy nhất cho cặp tên: giá trị (có nhược điểm riêng của nó).
Mẫu thiết kế cuối cùng tôi có thể nghĩ đến là lưu trữ giá trị thuộc tính thực tế trong bảng sản phẩm cụ thể và hoàn toàn không có bảng thuộc tính. Một cái gì đó như thế này:
Product product_[type]
---------------- ----------------
part_number (PK) part_number (FK)
UPC specific_attr1
price specific_attr2
... ...
Thay vì Khóa ngoài cho bảng khác, nó sẽ chứa giá trị thực như:
part_number color material
----------- ----- --------
1234 red plastic
Điều này sẽ loại bỏ sự tham gia và ngăn chặn creep bảng (có thể?). Tuy nhiên, điều này ngăn cản việc có một danh sách được ủy quyền của người dùng. Bạn có thể trả về tất cả các giá trị được nhập hiện tại cho một trường nhất định (ví dụ: màu sắc) nhưng điều này cũng loại bỏ ý tưởng về việc có một danh sách được ủy quyền của các giá trị đối với một thuộc tính nhất định.
Để có danh sách đó, bạn sẽ vẫn phải tạo bảng thuộc tính của nhóm Grab lấy túi hoặc có nhiều bảng (creep bảng) cho mỗi thuộc tính.
Điều này tạo ra nhược điểm lớn hơn (và tại sao tôi chưa bao giờ sử dụng phương pháp này) hiện có tên sản phẩm ở nhiều địa điểm.
Nếu bạn có giá trị màu của khăn đỏ và trong bảng thuộc tính của chủ sở hữu, và cũng lưu nó trong bảng sản phẩm [loại], một bản cập nhật cho bảng chủ Master sẽ gây ra sự cố toàn vẹn dữ liệu nếu ứng dụng không Cũng không cập nhật tất cả các bản ghi với giá trị cũ trong bảng sản phẩm_type '.
Vì vậy, sau khi tôi giải thích và phân tích dài dòng về kịch bản này, tôi nhận ra rằng đây không phải là một kịch bản hiếm gặp và thậm chí có thể đặt tên cho loại tình huống này.
Có những giải pháp được chấp nhận chung cho thách thức thiết kế này? Là số lượng lớn các phép nối có thể chấp nhận được nếu các bảng tương đối nhỏ? Việc lưu trữ tên thuộc tính, thay vì PK thuộc tính có thể được chấp nhận trong một số trường hợp không? Có giải pháp nào khác mà tôi không nghĩ tới không?
Một vài lưu ý về cơ sở dữ liệu / ứng dụng sản phẩm này:
- Sản phẩm không được cập nhật / thêm / xóa thường xuyên
- Các thuộc tính không được cập nhật / thêm / xóa thường xuyên
- Bảng được truy vấn thường xuyên nhất để đọc / trả lại thông tin
- Bộ nhớ đệm phía máy chủ được bật để lưu trữ kết quả của một truy vấn / kết quả đã cho
- Tôi dự định bắt đầu chỉ với một loại sản phẩm và mở rộng / thêm các loại khác theo thời gian và sẽ có khả năng hơn 10 loại khác nhau