В предыдущей серии этого сериала:
Автор постарался описать EAV модель опираясь теперь только на собственный опыт. Привёл живые примеры из жизни, описывая имеющиеся преимущества и иногда исправляя собственные ошибки.
Перейдём к недостаткам
Основной очевидный недостаток - сложность при построении запросов. Для того, чтобы добавить сущность необходимо минимум 2 команды вставки, при условии, что все атрибуты описаны ранее:
- 1 команда для вставки в таблицу сущностей;
- 1 команда для вставки значений описываемых атрибутов сущности.
Такая же ситуация при получении сведений - для получения всех характеристик сущности необходимо использовать либо команду JOIN по одной для каждого атрибута, либо вложенные запросы по одному для каждого требуемого атрибута.
Такое положение ухудшает читаемость кода в связи с его неоправданно большим объёмом, в отличие от запросов к структурам, которые построены по другим принципам.
В предыдущих статьях приведён ряд примеров, которые подтвердили этот недостаток, хотя и не имели такой цели.
Следующим недостатком является отсутствие контроля целостности данных. Разберём пример:
"Я - ужас, летящий на крыльях ночи! Я - чёрный плащ!"
Отразим в РСУБД стандартным подходом
Разместим данные в этой структуре
Используя именно такую структуру при размещении данных мы можем получить только исходную фразу и никакую другую. Фраза
"Я - плащ, летящий на крыльях ночи! Я - черный ужас!"
имеет смысл с точки зрения лексики, но сильно отличается от первоначального замысла и при соблюдении последовательного использования команд JOIN такая фраза в принципе не возможна, т.к. цельность фразы обеспечивается связями между таблицами.
Удаление одного свойства из таблицы Properties приведёт к исчезновению из результатов запроса не только самой записи, но и связанных с ней, подчинённых записей из таблицы PropertCharacteristics не зависимо от того, как эти связи настроены (delete/setNull).
Разместим теперь имеющиеся данные в структуре EAV, где используются поля разных типов, для хранения значений разных типов
Размещая данные в этой структуре мы можем пойти разными путями. В этот раз мы пойдём более сложным путём, добавив новые сущности и связи между ними.
Если в структуре, созданной стандартным подходом сразу очевидно, каким образом можно получить данные, то в этом случае есть проблемы с пониманием:
Так же, удаление одной из связанных сущностей не приведёт с null-результату запроса, а просто в некоторых полях будут значения null. К примеру если мы удалим плащ, это не изменит количество строк, возвращаемых запросом. Изменятся значения полей. Если удалим "Плащ", то фраза будет по--прежнему выводится, но уже в изменённом виде:
Я - ужас, летящий на крыльях ночи! Я - null null!
Такую ситуацию при стандартном подходе к размещению данных сложно повторить, тогда как в случае с EAV-моделью - это вполне законный случай.
Недопущение таких случаев должно регулироваться уже не на уровне СУБД, а на уровне клиентского ПО, что добавляет нагрузку разработчикам, которые его разрабатывают, снимая эту нагрузку с разработчиков СУБД.
Последний из основных недостатков - низкая производительность при построении запросов.
Этот недостаток относится как к увеличению нагрузки на разработчиков, которые на построение корректных запросов тратят большое времени, так и к возрастающим накладным расходам, при их исполнении.
Очевидно, что при прочих равных условиях (наличие индексов, выбранная СУБД, целостность и нормализация данных) запрос к таблицам, которые построены при использовании стандартного подхода к структуре данных (назовём структуру - А) будет выполняться быстрее, чем запрос к таблицам, которые построены при использовании EAV-модели (это будет структура Б).
В случае использования структуры А нет необходимости:
1. Использовать вложенные запросы
2. Для получения сведения для разных полей нет необходимости использовать одни и те же запросы
В то время, как в структуре Б при запросе у нас таблица valueAttributes используется несколько раз только в рамках одного запроса.
Тут даже бенчмарки проводить нет смысла - происходит много обращений к одним и тем же таблицам.
К итогам
Недостатки EAV-модели достаточно серьёзные, и при выборе такой структуры таблиц, для отражения сведений в СУБД, необходимо брать в расчёт не только жирные плюсы такого подхода, но и не менее жирные минусы.
Использовать EAV-модель данных я рекомендую только в следующих случаях:
- При постановке задачи имеется масса вводных, которые описаны не конкретно в связи с тем, что заказчик ещё сам не понимает, как это будет выглядеть. Бизнес не готов сформулировать полный перечень атрибутов и сущностей, которые подлежат хранению, т.к. либо бизнес о них в данный момент не знает, либо бизнес на их реализации на текущем этапе не настаивает.
- Никто из вашей команды не имеет физического доступа к серверам СУБД, включая команду администраторов.
- Вам необходимо за минимальное время собрать MVP, который будет эксплуатироваться заказчиком и одновременно с этим будут вноситься новые коррективы в список атрибутов и сущностей.
Даже если вы решили выбрать EAV-модель, то после окончания процесса введения новых атрибутов и сущностей важно начать задумываться (и не только) о переносе этой структуры в стандартную, с учётом уже имеющегося более полного списка атрибутов и сущностей.