Скажімо, товарний предмет магазину, у нього є спільні риси, такі як назва, опис, зображення, ціна тощо, які беруть участь у логіці у багатьох місцях і мають (напів) унікальні особливості, такі як годинник та пляжний м'яч описуються абсолютно іншими аспектами . Тож я думаю, що EAV підходить для зберігання цих (напів) унікальних особливостей?
Використання структури EAV для має кілька наслідків, які є компромісними.
Ви торгуєте "менше місця для рядка, оскільки у вас немає 100 стовпців, null
" проти "складніших запитів та моделі".
Наявність EAV зазвичай означає, що значення є рядком, в який можна заповнити будь-які дані. Це може мати наслідки для перевірки дійсності та обмежень. Розглянемо ситуацію, коли ти помістив кількість акумуляторів, що використовуються як щось у таблицю EAV. Ви хочете знайти ліхтарик, який використовує батареї розміром C, але менше 4 з них.
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'
...
Тут потрібно усвідомити, що не можна розумно використовувати індекс за значенням. Ви також не можете перешкодити комусь вводити щось, що не є цілим числом, або недійсне ціле число (використовує батареї '-1'), оскільки стовпець значення використовується знову і знову для різних цілей.
Це потім має наслідки в спробі написати модель для продукту. У вас будуть приємні набрані значення ... але ви також будете Map<String,String>
просто сидіти там з усілякими речами в ньому. Це може мати подальші наслідки при серіалізації його до XML або Json та складності спроб зробити перевірку чи запити проти цих структур.
Деякі альтернативи чи модифікації шаблону, який слід розглянути, - це замість вільної форми форми мати іншу таблицю з дійсними ключами. Це означає, що замість того, щоб проводити порівняння рядків у базі даних, ви перевіряєте рівність іноземних ключових ідентифікаторів. Зміна самого ключа робиться в одному місці. У вас є відомий набір ключів, що означає, що їх можна зробити як перерахунок.
Ви також можете мати пов’язані таблиці, що містять атрибути певного класу продукту. У продуктовому відділі може бути ще одна таблиця, яка містить кілька атрибутів, пов’язаних із нею, які будівельні матеріали не потребують (і навпаки).
+----------+ +--------+ +---------+
|Grocery | |Product | |BuildMat |
|id (fk) +--->|id (pk) |<---+id (fk) |
|expiration| |desc | |material |
|... | |img | |... |
+----------+ |price | +---------+
|... |
+--------+
Бувають випадки, коли особливо потрібна таблиця EAV.
Розглянемо ситуацію, коли ти не просто пишеш систему інвентаризації для своєї компанії, де ти знаєш кожен товар та кожен атрибут. Ви зараз пишете систему інвентаризації, щоб продати іншим компаніям. Ви не можете знати кожен атрибут кожного продукту - їх потрібно буде визначити.
Однією ідеєю є "ми дозволимо клієнтові змінити таблицю", і це просто погано (ви потрапляєте в метапрограмування для структур таблиць, оскільки ви вже не знаєте, що там, де вони можуть по- царському зіпсувати структуру або пошкодити додаток, вони мають доступ робити неправильні речі, і наслідки цього доступу набувають значного значення). Більше про цей шлях у MVC4: Як створити модель під час виконання?
Натомість ви створюєте адміністративний інтерфейс для таблиці EAV та дозволяєте використовувати його. Якщо замовник хоче створити запис для "polkadots", він переходить до таблиці EAV, і ви вже знаєте, як з цим боротися.
Приклад цього можна побачити в моделі бази даних для Redmine, ви можете побачити таблицю custom_fields, а таблицю custom_values - це частини EAV, що дозволяє розширити систему.
Зауважте, що якщо ви знайдете всю свою структуру таблиці, щоб вона виглядала як EAV, а не реляційна, ви можете подивитися на KV-аромат NoSQL (cassandra, redis, Mongo, ...). Зрозумійте, що вони часто мають інші компроміси в їх дизайні, які можуть бути або не відповідати тому, для чого ви його використовуєте. Однак вони спеціально розроблені з метою створення структури EAV.
Ви можете прочитати SQL vs NoSQL для системи управління запасами
Слідуючи такому підходу з базою даних NoSQL, орієнтованою на документ (couch, mongo), ви можете вважати, що кожен товарний запас є документом на диску ... витягування всього в одному документі відбувається швидко. Крім того, документ структурований так, що ви можете швидко витягнути будь-яку одну річ. З іншого боку, пошук у всіх документах речей, які відповідають певному атрибуту, може мати меншу продуктивність (порівняйте, використовуючи "grep" проти всіх файлів) ... все це є компромісом.
Іншим підходом був би LDAP, де можна було б встановити базу з усіма пов’язаними з нею елементами, але тоді також було б застосовано до неї додаткові класи об’єктів для інших типів елементів. (див. інвентаризацію системи за допомогою LDAP )
Коли ви спуститеся по цій стежці, ви можете виявити щось, що точно відповідає тому, що ви шукаєте ... хоча все відбувається з деякими компромісами.