Entity-attribute-value (EAV) model

W standardowym podejściu do projektowania bazy danych, tworzymy tyle tabel ile mamy encji, a w każdej tabeli, tworzymy tyle kolumn ile dana encja ma atrybutów. Rozwiązanie to sprawdza się w relatywnie nieskomplikowanych projektach. Istnieją jednak 2 sytuacje, gdzie takie zwykłe rozwiązanie może powodować poważne problemy.

1. Jeżeli dana encja ma wiele atrybutów, ale nie są wykorzystywane naraz, to otrzymamy sytuację, gdzie tabela będzie posiadać bardzo wiele pustych miejsc. Z matematycznego punktu widzenia, nazywa się to macierzą rzadką i wymaga znacznie więcej miejsca i obliczeń niż jest to absolutnie niezbędne.

2. Kiedy tworzymy aplikację, która ma spełniać zadanie frameworku programistycznego, powinniśmy dać programiście możliwość dostępu do bazy danych. Jednak, zmiana struktury bazy danych za każdym razem, gdy programista chce tworzyć nowe atrybuty i encje wiąże się z licznymi negatywnymi konsekwencjami m.in. dotyczącymi bezpieczeństwa, integralności, czytelności itd.

Właśnie dlatego powstał wzorzec programistyczny o nazwie EAV, szeroko stosowany np. przez system Magento.

W najprostszym przypadku modelu EAV potrzebuemy tylko 3 tabele. Pierwsza o nazwie Encje, która charakteryzuje opisywane przez bazę danych obiekty. Druga to Atrybuty, która charakteryzuje atrybuty, które mogą posiadać obiekty. Trzecia to Wartości, która trzyma wartości atrybutów. Oczywiście tabele są połączone odpowiednio kluczami obcymi. Poniższy przykład zilustruje to co jest napisane powyżej.

Simple_EAV

Jak widać, aby stworzyć nową encję wystarczy dodać do tabeli Encje wiersz. Encje mają wyszczególniony jeden przykładowy parametr opisujący, czy są one w jakiś sposób widoczne w systemie. Aby stworzyć nowy atrybut, wystarczy dodać rekord do tabeli Atrybuty. W naszym przypadku, podajemy również w tym rekordzie żądany typ, jaki teoretycznie ma posiadać dany atrybut. No i gdy chcemy przypisać danemu atrybutowi danej encji wartość, po prostu dodajemy rekord to tabeli Wartości podając odpowiednie klucze. Pełna elastyczność…

Takie rozwiązanie ma jednak wady. Nie możemy korzystać ze wszystkich typów danych, które oferuje baza, a jedynie (w naszym przypadku) z VARCHAR. Aby rozwiązać ten problem, zmodyfikujemy trochę nasz schemat.

Big_EAV

Teraz dla każdego typu danych, mamy inną tabelę z wartościami. To, w której tabeli system ma szukać wartości atrybutu dla danej encji wiemy po parametrze type w tabeli Atrybuty.

Ot i cała tajemnica modelu EAV rozwiązana…