Załóżmy, że produkt jest sklepowy, ma wspólne cechy, takie jak nazwa, opis, obraz, cena itp., Które biorą udział w logice wielu miejsc i ma (pół) unikalne cechy, takie jak zegarek i piłka plażowa byłyby opisywane zupełnie innymi aspektami . Więc myślę, że EAV byłby odpowiedni do przechowywania tych (pół) unikalnych funkcji?
Korzystanie ze struktury EAV dla ma kilka implikacji, które są kompromisami.
Wymieniasz „mniej miejsca dla wiersza, ponieważ nie masz 100 kolumn, które są null
„ przeciw ”bardziej złożonym zapytaniom i modelom”.
Posiadanie EAV zazwyczaj oznacza, że wartość jest łańcuchem, w który można włożyć dowolne dane. Ma to następnie wpływ na sprawdzanie poprawności i ograniczeń. Rozważ sytuację, w której umieściłeś liczbę używanych baterii jako coś w tabeli EAV. Chcesz znaleźć latarkę, która używa baterii w rozmiarze C, ale mniej niż 4 z nich.
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'
...
Należy tutaj zdać sobie sprawę, że nie można rozsądnie użyć indeksu wartości. Nie można również uniemożliwić komuś wstawienia czegoś, co nie jest liczbą całkowitą lub nieprawidłową liczbą całkowitą (używa baterii „-1”), ponieważ kolumna wartości jest używana wielokrotnie do różnych celów.
Ma to następnie wpływ na próbę napisania modelu dla produktu. Będziesz miał ładne, wpisane wartości ... ale będziesz też Map<String,String>
siedział tam z różnego rodzaju rzeczami . Ma to dalsze implikacje podczas szeregowania go do formatu XML lub Json oraz złożoność próby sprawdzania poprawności lub zapytań przeciwko tym strukturom.
Niektóre alternatywy lub modyfikacje wzorca, które należy wziąć pod uwagę, to zamiast klucza swobodnego, mieć inną tabelę z prawidłowymi kluczami. Oznacza to, że zamiast porównywania ciągów w bazie danych, sprawdzasz równość identyfikatorów kluczy obcych. Zmiana samego klucza odbywa się w jednym miejscu. Masz znany zestaw kluczy, co oznacza, że można je wykonać jako wyliczenie.
Możesz także mieć powiązane tabele zawierające atrybuty określonej klasy produktu. Dział spożywczy może mieć inny stół z kilkoma powiązanymi z nim atrybutami, których materiały budowlane nie potrzebują (i odwrotnie).
+----------+ +--------+ +---------+
|Grocery | |Product | |BuildMat |
|id (fk) +--->|id (pk) |<---+id (fk) |
|expiration| |desc | |material |
|... | |img | |... |
+----------+ |price | +---------+
|... |
+--------+
Są chwile, które szczególnie wymagają tabeli EAV.
Zastanów się nad sytuacją, w której piszesz nie tylko system inwentaryzacji dla swojej firmy, w którym znasz każdy produkt i każdy atrybut. Piszesz teraz system zapasów, aby sprzedawać je innym firmom. Nie możesz znać każdego atrybutu każdego produktu - będą musieli je zdefiniować.
Jednym z pomysłów, który się pojawia, jest „pozwolimy klientowi modyfikować tabelę”, a to jest po prostu złe (wchodzisz w meta-programowanie struktur tabel, ponieważ nie wiesz już, gdzie jest, mogą po królewsku zepsuć strukturę lub uszkodzić aplikacji, mają oni dostęp do robienia złych rzeczy, a implikacje tego dostępu stają się znaczące). W MVC4 jest więcej na temat tej ścieżki : jak stworzyć model w czasie wykonywania?
Zamiast tego tworzysz interfejs administracyjny do tabeli EAV i zezwalasz na jego użycie. Jeśli klient chce utworzyć wpis dla „polkadots”, wchodzi do tabeli EAV i już wiesz, jak sobie z tym poradzić.
Przykład tego można zobaczyć w modelu bazy danych dla Redmine , można zobaczyć tabelę custom_fields i tabelę custom_values - są to części EAV, które pozwalają na rozbudowę systemu.
Zauważ, że jeśli znajdziesz całą strukturę tabeli, która wygląda bardziej jak EAV niż relacyjna, możesz spojrzeć na smak KV NoSQL (Cassandra, Redis, Mongo, ...). Zdaj sobie sprawę, że często mają one inne kompromisy w projekcie, które mogą, ale nie muszą być odpowiednie do tego, do czego go używasz. Są one jednak specjalnie zaprojektowane z myślą o strukturze EAV.
Możesz przeczytać SQL vs NoSQL dla systemu zarządzania zapasami
Postępując zgodnie z tym podejściem z zorientowaną na dokumenty bazą danych NoSQL (kanapa, mongo), możesz uznać każdy element ekwipunku za dokument na dysku ... wyciągnięcie wszystkiego z jednego dokumentu jest szybkie. Co więcej, dokument ma taką strukturę, że można szybko wyciągnąć jedną rzecz. Z drugiej strony wyszukiwanie we wszystkich dokumentach elementów pasujących do określonego atrybutu może mieć mniejszą wydajność (porównaj używając „grep” względem wszystkich plików) ... to wszystko jest kompromisem.
Innym podejściem byłby LDAP, w którym miałby się bazę ze wszystkimi powiązanymi z nim elementami, ale wówczas zastosowanoby również dodatkowe klasy obiektów dla innych typów elementów. (patrz Inwentaryzacja systemu za pomocą LDAP )
Po pójść tą drogą, to może znaleźć coś, co odpowiada dokładnie to, czego szukasz ... mimo wszystko pochodzi z pewnych kompromisów.