Giả sử thực thể sản phẩm cửa hàng, nó có các tính năng phổ biến, như tên, mô tả, hình ảnh, giá cả, v.v., tham gia logic nhiều nơi và có (bán) các tính năng độc đáo, như đồng hồ và bóng bãi biển sẽ được mô tả bởi các khía cạnh hoàn toàn khác nhau . Vì vậy, tôi nghĩ rằng EAV sẽ phù hợp để lưu trữ các tính năng (bán) độc đáo đó?
Sử dụng cấu trúc EAV cho một số ý nghĩa là sự đánh đổi.
Bạn đang giao dịch với 'ít không gian hơn cho hàng vì bạn không có 100 cột null
' chống lại 'các truy vấn và mô hình phức tạp hơn'.
Có EAV thường có nghĩa là giá trị là một chuỗi mà người ta có thể nhét bất kỳ dữ liệu nào vào. Điều này sau đó có ý nghĩa về kiểm tra tính hợp lệ và ràng buộc. Hãy xem xét tình huống bạn đã đặt số lượng pin được sử dụng như một cái gì đó trong bảng EAV. Bạn muốn tìm một đèn pin sử dụng pin cỡ C, nhưng ít hơn 4 trong số chúng.
select P.sku
from
products P
attrib Ab on (P.sku = Ab.sku and Ab.key = "batteries")
attrib Ac on (P.sku = Ac.sku and Ac.key = "count")
where
cast(Ac.value as int) < 4
and Ab.value = 'C'
...
Điều cần nhận ra ở đây là bạn không thể sử dụng chỉ mục một cách hợp lý trên giá trị. Bạn cũng không thể ngăn ai đó đưa vào thứ gì đó không phải là số nguyên ở đó hoặc số nguyên không hợp lệ (sử dụng pin '-1') vì cột giá trị được sử dụng nhiều lần cho các mục đích khác nhau.
Điều này sau đó có ý nghĩa trong việc cố gắng viết một mô hình cho sản phẩm. Bạn sẽ có những giá trị được gõ tốt ... nhưng bạn cũng sẽ Map<String,String>
chỉ ngồi đó với đủ thứ trong đó. Điều này sau đó có ý nghĩa hơn nữa khi tuần tự hóa nó thành XML hoặc Json và sự phức tạp của việc cố gắng xác thực hoặc truy vấn đối với các cấu trúc đó.
Một số lựa chọn thay thế hoặc sửa đổi cho mẫu cần xem xét là thay vì khóa biểu mẫu miễn phí, để có một bảng khác có khóa hợp lệ. Nó có nghĩa là thay vì thực hiện so sánh chuỗi trong cơ sở dữ liệu, bạn đang kiểm tra tính bằng nhau của id khóa ngoài. Thay đổi chính nó được thực hiện tại một điểm. Bạn đã có một bộ khóa được biết đến, điều đó có nghĩa là chúng có thể được thực hiện như một enum.
Bạn cũng có thể có các bảng liên quan có chứa các thuộc tính của một loại sản phẩm cụ thể. Một bộ phận tạp hóa có thể có một bảng khác có một số thuộc tính liên quan đến nó mà vật liệu xây dựng không cần (và ngược lại).
+----------+ +--------+ +---------+
|Grocery | |Product | |BuildMat |
|id (fk) +--->|id (pk) |<---+id (fk) |
|expiration| |desc | |material |
|... | |img | |... |
+----------+ |price | +---------+
|... |
+--------+
Có những lúc đặc biệt gọi cho bảng EAV.
Hãy xem xét tình huống mà bạn không chỉ viết một hệ thống kiểm kê cho công ty của bạn, nơi bạn biết mọi sản phẩm và mọi thuộc tính. Bây giờ bạn đang viết một hệ thống hàng tồn kho để bán cho các công ty khác. Bạn không thể biết mọi thuộc tính của mọi sản phẩm - họ sẽ cần xác định chúng.
Một ý tưởng mà đi ra là "chúng tôi sẽ cho khách hàng sửa đổi bảng" và điều này chỉ là xấu (bạn nhận được vào meta-lập trình cho các cấu trúc bảng bởi vì bạn không còn biết gì là ở đâu, họ có thể royally mess lên cấu trúc hoặc bị hỏng ứng dụng, họ đã có quyền truy cập để làm những điều sai trái và ý nghĩa của việc truy cập đó trở nên quan trọng). Có nhiều hơn về đường dẫn này tại MVC4: Làm thế nào để tạo mô hình trong thời gian chạy?
Thay vào đó, bạn tạo giao diện quản trị cho bảng EAV và cho phép sử dụng giao diện đó. Nếu khách hàng muốn tạo một mục nhập cho 'polkadots', nó sẽ đi vào bảng EAV và bạn đã biết cách xử lý vấn đề đó.
Một ví dụ về điều này có thể được nhìn thấy trong mô hình cơ sở dữ liệu cho Redmine, bạn có thể thấy bảng custom_fields và bảng custom_values - đó là những phần của EAV cho phép hệ thống được mở rộng.
Lưu ý rằng nếu bạn thấy toàn bộ cấu trúc bảng của mình trông giống EAV hơn là quan hệ, bạn có thể muốn xem hương vị KV của NoQuery (cassandra, redis, Mongo, ...). Nhận ra rằng những điều này thường đi kèm với sự đánh đổi khác trong thiết kế của họ có thể phù hợp hoặc không phù hợp với những gì bạn đang sử dụng. Tuy nhiên, chúng được thiết kế đặc biệt với mục đích của cấu trúc EAV.
Bạn có thể muốn đọc SQL vs NoQuery cho hệ thống quản lý kho
Theo cách tiếp cận này với cơ sở dữ liệu NoQuery theo định hướng tài liệu (couch, mongo), bạn có thể coi mỗi mục kiểm kê là một tài liệu trên đĩa ... kéo mọi thứ trong một tài liệu trở nên nhanh chóng. Hơn nữa, tài liệu được cấu trúc để bạn có thể rút ra bất kỳ một điều duy nhất nào nhanh chóng. Mặt khác, tìm kiếm tất cả các tài liệu cho những thứ phù hợp với một thuộc tính cụ thể có thể có hiệu suất thấp hơn (so sánh sử dụng 'grep' với tất cả các tệp) ... tất cả đều là một sự đánh đổi.
Một cách tiếp cận khác sẽ là LDAP trong đó người ta sẽ có một cơ sở với tất cả các mục được liên kết của nó, nhưng sau đó cũng sẽ có các lớp đối tượng bổ sung được áp dụng cho nó cho các loại mục khác. (xem Kiểm kê hệ thống bằng LDAP )
Khi bạn đi xuống con đường này, bạn có thể tìm thấy thứ gì đó phù hợp chính xác với những gì bạn đang tìm kiếm ... mặc dù mọi thứ đều đi kèm với một số sự đánh đổi.