Я подумываю использовать модель сущность-атрибут-значение (EAV) для некоторых вещей в одном из проектов, но все вопросы об этом в Stack Overflow заканчиваются ответами, называющими EAV анти-паттерном.
Но мне интересно, так ли это во всех случаях?
Допустим, сущность продукта магазина, у него есть общие черты, такие как имя, описание, изображение и цена, которые во многих местах участвуют в логике, и (полу) уникальные особенности, такие как часы и пляжный мяч, будут описаны совершенно по-разному. Поэтому я думаю, что EAV подойдет для хранения этих (полу) уникальных функций.
Все это предполагает, что для отображения списка товаров достаточно информации в таблице товаров (это означает, что EAV не задействован) и просто при показе одного товара / при сравнении до 5 товаров / и т. Д. данные сохраняются с использованием EAV.
Я видел такой подход в Magento Commerce, и он довольно популярен, так есть ли случаи, когда EAV является разумным?
Ответы:
https://web.archive.org/web/20140831134758/http://www.dbforums.com/database-concepts-design/1619660-otlt-eav-design-why-do-people-hate.html
EAV предоставляет разработчику гибкость в определении схемы по мере необходимости, и это хорошо в некоторых обстоятельствах.
С другой стороны, он работает очень плохо в случае плохо определенного запроса и может поддерживать другие плохие методы.
Другими словами, EAV дает вам достаточно веревки, чтобы повеситься, и в этой отрасли все должно быть разработано с наименьшим уровнем сложности, потому что парень, заменяющий вас в проекте, скорее всего, будет идиотом.
источник
В двух словах, EAV полезен, когда ваш список атрибутов часто увеличивается, или когда он настолько большой, что большинство строк будут заполнены в основном значениями NULL, если вы сделаете каждый атрибут столбцом. Это становится анти-паттерном, когда используется вне этого контекста.
источник
CREATE TABLE
для нового атрибута?Использование структуры EAV для имеет несколько последствий, которые являются компромиссами.
Вы торгуете «меньшим пространством для строки, потому что у вас нет 100 столбцов, которые
null
« против »более сложных запросов и модели».Наличие EAV обычно означает, что значение является строкой, в которую можно вставить любые данные. Это имеет значение для проверки правильности и ограничения. Рассмотрим ситуацию, когда вы указали количество используемых батарей в таблице EAV. Вы хотите найти фонарик, который использует батареи размера С, но менее 4 из них.
Здесь нужно понять, что вы не можете разумно использовать индекс для значения. Вы также не можете запретить кому-либо вставлять что-то, что не является целым числом или недопустимым целым числом (использует батарейки -1), поскольку столбец значений используется снова и снова для различных целей.
Это имеет значение при попытке написать модель для продукта. У вас будут хорошие напечатанные значения ... но вы также будете
Map<String,String>
просто сидеть там со всеми видами вещей в нем. Это затем имеет дополнительные последствия при сериализации его в XML или Json и сложности попыток проверки или запросов к этим структурам.Некоторые альтернативы или модификации рассматриваемого шаблона вместо ключа свободной формы должны иметь другую таблицу с допустимыми ключами. Это означает, что вместо сравнения строк в базе данных вы проверяете равенство идентификаторов внешних ключей. Смена самого ключа производится в одном месте. У вас есть известный набор ключей, что означает, что они могут быть выполнены как enum.
Вы также можете иметь связанные таблицы, которые содержат атрибуты определенного класса продукта. В продуктовом отделе может быть другая таблица, с которой связано несколько атрибутов, которые не нужны строительным материалам (и наоборот).
Есть моменты, которые особенно требуют таблицы EAV.
Рассмотрим ситуацию, когда вы не просто пишете систему инвентаризации для своей компании, где вы знаете каждый продукт и каждый атрибут. Вы сейчас пишете систему инвентаризации для продажи другим компаниям. Вы не можете знать каждый атрибут каждого продукта - они должны будут определить их.
Одна идея, которая выходит: «мы позволим клиенту модифицировать таблицу», и это просто плохо (вы попадаете в метапрограммирование для структур таблиц, потому что вы больше не знаете, что, где, они могут по- королевски испортить структуру или испортить приложение, у них есть доступ, чтобы делать неправильные вещи, и последствия этого доступа становятся значительными). Есть больше об этом пути в MVC4: Как создать модель во время выполнения?
Вместо этого вы создаете административный интерфейс для таблицы EAV и разрешаете его использовать. Если клиент хочет создать запись для «polkadots», он попадает в таблицу EAV, и вы уже знаете, как с этим справиться.
Пример этого можно увидеть в модели базы данных для Redmine, где вы можете увидеть таблицу custom_fields и таблицу custom_values - это те части EAV, которые позволяют расширять систему.
Обратите внимание, что если вы обнаружите, что вся структура вашей таблицы выглядит как EAV, а не как реляционная, вы, возможно, захотите взглянуть на разновидность KV NoSQL (cassandra, redis, Mongo, ... ...). Поймите, что они часто идут с другими компромиссами в их дизайне, которые могут или не могут соответствовать тому, для чего вы его используете. Тем не менее, они специально разработаны с целью структуры EAV.
Вы можете прочитать SQL против NoSQL для системы управления запасами
Следуя такому подходу с базой данных NoSQL, ориентированной на документы (couch, mongo), вы можете рассматривать каждый элемент инвентаря как документ на диске ... быстро собрать все в одном документе. Кроме того, документ структурирован так, что вы можете быстро извлечь что-то одно. С другой стороны, поиск во всех документах вещей, которые соответствуют определенному атрибуту, может иметь меньшую производительность (сравните, используя 'grep' со всеми файлами) ... все это компромисс.
Другим подходом может быть LDAP, где у каждого будет база со всеми связанными с ней элементами, но затем к нему будут применены дополнительные классы объектов для других типов элементов. (см. Инвентаризация системы с использованием LDAP )
Как только вы пойдете по этому пути, вы можете найти что-то, что точно соответствует тому, что вы ищете ... хотя все идет с некоторыми компромиссами.
источник
6 лет спустя
Теперь, когда JSON в Postgres здесь, у нас есть еще один вариант для тех, кто использует Postgres. Если вы хотите прикрепить к продукту только некоторые дополнительные данные, тогда ваши потребности довольно просты. Пример:
Вот более плавное введение в JSON в Postgres: https://www.compose.com/articles/is-postgresql-your-next-json-database/ .
Обратите внимание, что Postgres на самом деле хранит JSONB, а не обычный текст JSON, и он поддерживает индексы для полей внутри документа / поля JSONB, если вы обнаружите, что действительно хотите запросить эти данные.
Также обратите внимание, что поля внутри поля JSONB не могут быть изменены индивидуально с помощью запроса UPDATE; вам придется заменить все содержимое поля JSONB.
Этот ответ не может напрямую касаться вопроса, но он предлагает альтернативу шаблону EAV, который должен рассмотреть каждый, кто размышляет над первоначальным вопросом.
источник
jsonb_set()
Postgres 9.5 и более поздних версиях есть функция, предназначенная именно для этого. (Статья, на которую вы ссылались по ссылкам, в свою очередь, относится к новой статье, в которой обсуждаются дополнения к 9.5 .)Обычно люди смотрят иначе, если вы используете их для поиска таблиц, или в других ситуациях, когда преимущество состоит в том, чтобы не создавать таблицы для одного или двух сохраненных значений. Ситуация, которую вы описываете, когда вы в основном храните свойства элемента, звучит совершенно нормально (и нормализуется). Расширение таблицы для хранения переменного количества атрибутов элементов - плохая идея.
Для общего случая хранения разрозненных данных в длинной тонкой таблице ... Вы не должны бояться создавать новые таблицы, если вам нужно, и иметь только одну или две длинные тонкие таблицы не намного лучше, чем иметь только одну или две короткие толстые таблицы.
Это, как говорится, я известен тем, что использовал таблицы EAV для регистрации. У них есть хорошая полезность.
источник
EAV изменяет проблему явной структуры, подразумеваемого восприятия. Вместо того, чтобы говорить, что X - это таблица со столбцами A и B. Вы подразумеваете, что столбцы A и B образуют таблицу X. В некотором смысле все наоборот, но не обязательно однозначное отображение, обязательно. Можно сказать, что A и B отображаются на таблицу (или тип) X и Y. Это может быть важно в более сложной области, где имеет значение контекст.
Я изучал Datomic, для такого типа подхода, и я думаю, что это очень полезная и мощная система с ограничениями на то, что вы должны с ней делать (не то, что вы не могли).
То, что EAV будет медленным или «даст вам достаточно веревки, чтобы повеситься», - это не утверждение, с которым я бы согласился. Скорее, я бы уделил больше внимания сильным сторонам EAV, и, если это подходит вашему проблемному пространству, вы должны рассмотреть его.
Мой опыт показывает, что это замечательный, почти без ограничений подход к моделированию. В частности, в случае с Datomic они навязывают набор семантики поверх всего. Любое решение по моделированию, которое моделирует отношения, может свободно переходить от одного ко многим без необходимости перепроектировать столбцы / таблицы. Вы также можете вернуться назад, если ограничение не нарушает инвариант. Под капотом все тоже самое.
На мой взгляд, проблема с EAV заключалась в отсутствии такой реализации, как Datomic. Так как это вопрос о EAV, я не хочу в восторге от Datomic, но это одна из тех вещей, где, я думаю, они все поняли относительно EAV.
источник