База данных значений атрибутов сущностей против строгой реляционной модели электронной коммерции

136

Можно с уверенностью сказать, что модель базы данных EAV / CR плохая. Это сказало,

Вопрос: Какую модель базы данных, технику или шаблон следует использовать для работы с «классами» атрибутов, описывающих продукты электронной коммерции, которые можно изменить во время выполнения?

В хорошей базе данных электронной коммерции вы будете хранить классы опций (например, разрешение телевизора и разрешение для каждого телевизора, но следующий продукт может не быть телевизором и не иметь «разрешения телевизора»). Как вы храните их, эффективно выполняете поиск и позволяете своим пользователям настраивать типы продуктов с помощью переменных полей, описывающих их продукты? Если поисковая система обнаруживает, что клиенты обычно ищут телевизоры на основе глубины консоли, вы можете добавить глубину консоли в свои поля, а затем добавить одну глубину для каждого типа телевизионного продукта во время выполнения.

Есть хорошая общая черта среди хороших приложений электронной коммерции, где они показывают набор продуктов, а затем имеют «развернутые» боковые меню, в которых вы можете видеть «Разрешение ТВ» в качестве заголовка, и пять самых распространенных ТВ-разрешений для найдено множество. Вы нажимаете один, и он показывает только телевизоры с таким разрешением, что позволяет вам продолжить детализацию, выбрав другие категории в боковом меню. Эти параметры будут динамическими атрибутами продукта, добавляемыми во время выполнения.

Дальнейшее обсуждение:

Короче говоря, есть ли ссылки в Интернете или описания моделей, которые могли бы "академически" исправить следующую настройку? Я благодарю Ноэля Кеннеди за предложение таблицы категорий, но потребность может быть больше, чем это. Ниже я описываю это по-другому, пытаясь подчеркнуть значение. Мне может потребоваться коррекция точки зрения для решения проблемы, или мне, возможно, придется углубиться в EAV / CR.

Люблю положительный ответ на модель EAV / CR. Все мои коллеги-разработчики говорят, что Джеффри Кемп затронул ниже: «новые объекты должны быть смоделированы и спроектированы профессионалом» (вырванный из контекста, прочитайте его ответ ниже). Проблема в:

  • объекты добавляют и удаляют атрибуты еженедельно
    (ключевые слова для поиска определяют будущие атрибуты)
  • новые объекты прибывают еженедельно
    (продукты собираются из частей)
  • старые объекты уходят еженедельно
    (в архиве, менее популярные, сезонные)

Клиент хочет добавить атрибуты к продуктам по двум причинам:

  • отдел / поиск по ключевым словам / таблица сравнения между похожими продуктами
  • Конфигурация потребительского товара перед оформлением заказа

Атрибуты должны иметь значение, а не только поиск по ключевым словам. Если они хотят сравнить все пирожные с «глазурью из взбитых сливок», они могут щелкнуть по пирожным, выбрать тему дня рождения, щелкнуть по глазировке со взбитыми сливками, а затем проверить все интересные пирожные, зная, что у них всех есть глазурь из взбитых сливок. Это не характерно для тортов, просто пример.

Захари Скотт
источник
Почему вы не можете просто иметь таблицу категории с внешним ключом, ссылающимся на себя?
Ноэль Кеннеди
29
Не безопасно и не точно сказать, что модель базы данных EAV плохая, потому что она хорошо подходит для некоторых приложений.
spencer7593
Что если вы украсите различные объекты с различными свойствами, наследуя от родителя, как в Entity Framework 4? Как это сохраняется эти объекты?
Захари Скотт
1
Просто вернемся к этой замечательной статье об опыте одного консультанта с системой, основанной на экстремальной версии EAV. Прочитайте это! simple-talk.com/opinion/opinion-pieces/bad-carma
Джеффри Кемп
1
EAV - очень жизнеспособная модель базы данных. Я работаю над подобной проблемой, как вы, и решение EAV. Я бы порекомендовал следующую статью: sqlblog.com/blogs/aaron_bertrand/archive/2009/11/19/…
Сандор

Ответы:

75

Есть несколько общих плюсов и минусов, о которых я могу подумать, бывают ситуации, когда один лучше другого:

Вариант 1, модель EAV:

  • Pro: меньше времени на разработку и разработку простого приложения
  • Pro: новые сущности легко добавляются (могут быть добавлены даже пользователями?)
  • Pro: «универсальные» компоненты интерфейса
  • Con: сложный код, необходимый для проверки простых типов данных
  • Con: гораздо более сложный SQL для простых отчетов
  • Против: сложные отчеты могут стать практически невозможными
  • Против: низкая производительность для больших наборов данных

Вариант 2. Моделирование каждого объекта в отдельности:

  • Против: больше времени требуется для сбора требований и дизайна
  • Против: новые лица должны быть смоделированы и разработаны профессиональным
  • Con: настраиваемые компоненты интерфейса для каждого объекта
  • Pro: ограничения типа данных и проверка просты в реализации
  • Pro: SQL легко написать, легко понять и отладить
  • Pro: даже самые сложные отчеты относительно просты
  • Pro: лучшая производительность для больших наборов данных

Вариант 3, Комбинация (моделировать объекты «правильно», но добавлять «расширения» для пользовательских атрибутов для некоторых / всех объектов)

  • Pro / Con: больше времени требуется для сбора требований и дизайна, чем вариант 1, но, возможно, не так много, как вариант 2 *
  • Против: новые лица должны быть смоделированы и разработаны профессиональным
  • Pro: новые атрибуты могут быть легко добавлены позже
  • Con: сложный код, необходимый для проверки простых типов данных (для пользовательских атрибутов)
  • Против: все еще требуются компоненты пользовательского интерфейса, но для пользовательских атрибутов возможны общие компоненты интерфейса
  • Против: SQL становится сложным, как только в отчет включается любой пользовательский атрибут
  • Con: хорошая производительность в целом, если только вы не начинаете искать или сообщать по пользовательским атрибутам

* Я не уверен, что вариант 3 обязательно сэкономит время на этапе проектирования.

Лично я склоняюсь к варианту 2 и избегаю EAV, где это возможно. Однако для некоторых сценариев пользователям нужна гибкость, которая поставляется с EAV; но это идет с большой ценой.

Джеффри Кемп
источник
Что если у вас была одна таблица с индексами для текстовых значений 1-n, то в C # (в оперативной памяти) сопоставьте то, что вы хотите, с тем, что вам нужно. Это все равно будет работать как EAV, но «совпадения» будут моделями домена. Вроде как сериализация, но вы можете использовать SQL-запросы в индексированных текстовых полях. Нет множественного выбора на запись. Вся «стоимость» происходит в оперативной памяти.
Захари Скотт
1
@Zim, это звучит во многом как вариант 3. Каждая строка имеет 1-n дополнительных «общих» столбцов, и данные, хранящиеся в них, интерпретируются на уровне приложения. Вы получаете преимущество в производительности, если все данные одной записи хранятся в одном месте. Однако, метаданные об этих столбцах должны где-то храниться, и именно здесь закрадывается стоимость. Конечно, мы можем кэшировать метаданные в оперативной памяти, но это все равно стоит больше, чем моделирование домена непосредственно в коде приложения. Конечно, лучше, чем полноценная модель EAV!
Джеффри Кемп
1
+10000 Отличный ответ. В настоящее время люди экономят на разработке базы данных и сборе требований. Они лучше написали бы в сто раз больше строк кода, чтобы создать хороший дизайн.
Тулаинс Кордова
Вам не нужно больше проектировать реляционную опцию (2), чем опцию EAV (1), если вы только предоставляете структуру варианта 1. А реляционный интерфейс является общим для метаданных, описывающих эту структуру. Это удаляет все варианты 2 минусов. Однако вы забыли, что единственное фактическое Con: DDL может быть слишком медленным в управлении таблицами.
philipxy
Привет @philipxy, я не сказал "больше дизайна". Смысл EAV в том, что (предположительно) разработчик системы может тратить меньше времени на проектирование модели, оставляя эту работу по проектированию «пользователям» в дальнейшем (это отсутствие профессионального дизайна приводит к недостаткам, перечисленным для варианта 1) , Если EAV не приводит к экономии для дизайнера, это только добавляет масла в огонь для отказа от EAV из-под контроля. Кроме того, я не согласен с тем, что DDL «слишком медленный» - поскольку он требуется только в редких случаях (например, для исправления ошибок в модели или для реализации новых функций), его производительность должна быть относительно незначительной.
Джеффри Кемп
63

Можно с уверенностью сказать, что модель базы данных EAV / CR плохая.

Нет, это не так. Просто они неэффективно используют реляционные базы данных. Чисто хранилище ключей / значений прекрасно работает с этой моделью.

Теперь к вашему реальному вопросу: как хранить различные атрибуты и обеспечивать их поиск?

Просто используйте EAV. В вашем случае это будет одна дополнительная таблица. индексируйте его как по имени, так и по значению атрибута, большинство РСУБД будет использовать префиксное сжатие для повторений имен атрибутов, что делает его действительно быстрым и компактным.

EAV / CR становится ужасным, когда вы используете его для замены «настоящих» полей. Как и в случае с любым инструментом, его чрезмерное использование - это «плохо» и создает плохую репутацию.

Хавьер
источник
поэтому вопрос в том, что у меня есть 15 дополнительных полей для одной из моих категорий, и в модели eav требуется 16 соединений + главная таблица, поэтому создание 16 левых соединений для поиска по продуктам (и наличие 16, где, если клиент хочет) в 3-4 миллионах записей ( веб-сайт для продажи подержанных продуктов людьми) так что это низкое качество?
Бабак Фахихиан
2
Если эти «дополнительные поля» уже определены, то это определенно лучше всего сделать как «реальные поля». И, конечно, выполнение несвязанного количества объединений в большом запросе было бы тяжелым испытанием (но все же может быть в порядке!). То, что я сделал в проекте с большим количеством метаданных, - это разрешил любое количество «тегов» (как записей EAV) для «основного элемента», но «большой запрос» выбирает только некоторые предопределенные теги, ограничивая общее количество объединений. ( в настоящее время типична всего 4 метки и около 5 других соединений), и когда пользователь выбирает конкретный пункт, то он fetchs все , что связано, но для одного элемента.
Хавьер
но, конечно, эта конкретная система в настоящее время переносится в hstoreполе (только одна из причин, по которой мы используем PostgreSQL)
Хавьер
15
// Сейчас я хотел бы поговорить с вами о формате PSD Magento / Adobe .
// Magento / PSD не является хорошей платформой / форматом электронной коммерции . Magento / PSD - это даже не плохая платформа / формат электронной коммерции . Назвать это так было бы
// оскорбление других плохих платформ / форматов электронной коммерции , таких как Zencart или OsCommerce. Нет, Magento / PSD - ужасная платформа / формат электронной коммерции . имеющий
// работал над этим кодом уже несколько недель, я ненавижу Magento / PSD переросла в бушующий огонь
// это горит яростной страстью миллиона солнц.

http://code.google.com/p/xee/source/browse/trunk/XeePhotoshopLoader.m?spec=svn28&r=11#107

Внутренние модели в лучшем случае дурацкие, как будто кто-то вложил схему в непростую игру, запечатал ее и положил в шейкер для рисования ...

Реальный мир: я работаю над приложением промежуточного программного обеспечения, и вот один из запросов для получения информации об адресе.

CREATE OR REPLACE VIEW sales_flat_addresses AS
SELECT sales_order_entity.parent_id AS order_id, 
       sales_order_entity.entity_id, 
       CONCAT(CONCAT(UCASE(MID(sales_order_entity_varchar.value,1,1)),MID(sales_order_entity_varchar.value,2)), "Address") as type, 
       GROUP_CONCAT( 
         CONCAT( eav_attribute.attribute_code," ::::: ", sales_order_entity_varchar.value )
         ORDER BY sales_order_entity_varchar.value DESC
         SEPARATOR '!!!!!' 
       ) as data
  FROM sales_order_entity
       INNER JOIN sales_order_entity_varchar ON sales_order_entity_varchar.entity_id = sales_order_entity.entity_id
       INNER JOIN eav_attribute ON eav_attribute.attribute_id = sales_order_entity_varchar.attribute_id
   AND sales_order_entity.entity_type_id =12
 GROUP BY sales_order_entity.entity_id
 ORDER BY eav_attribute.attribute_code = 'address_type'

Точную адресную информацию для заказа, лениво

-

Резюме: используйте Magento только если:

  1. Вам дают большие мешки с деньгами
  2. Вы должны
  3. Наслаждайся болью
Vee
источник
Это старый пост, но я бы хотел найти его 3 месяца назад, когда начал проект Magento для клиента. +1 за аналогию ошеломляющего шейкера!
Trevorc
1
Довольно интересный, кажется, что magento является королем дорог с точки зрения систем электронной коммерции. Может быть, только это маркетинг очень хорош
герр
1
Magento не пользуется популярностью из-за уровня обслуживания, но из-за способности настраивать, позволяя любому реализовывать новые функции без изменений архитектуры или нескольких модификаций. Эта функция поставляется с оплатой.
Диего Мендес
Держитесь подальше от Magento 2, если вы хотите избежать тройной боли и большей боли сверху и для FE, и для BE
TheBlackBenzKid
15

Я удивлен, что никто не упомянул базы данных NoSQL.

Я никогда не практиковал NoSQL в производственном контексте (только что протестировал MongoDB и был впечатлен), но весь смысл NoSQL в том, что он способен сохранять элементы с различными атрибутами в одном и том же «документе».

Лукас Т
источник
Учтите, что для записи в MongoDB требуется блокировка на уровне базы данных и что это означает для параллельного производственного трафика.
Билл Карвин
Учтите, что длительность блокировки составляет порядка микросекунд.
Привет, мир,
12

Там, где производительность не является основным требованием, как в приложении типа ETL, EAV имеет еще одно явное преимущество: дифференциальное сохранение.

Я реализовал ряд приложений, в которых требовалось переопределить возможность просмотра истории объекта домена от его первой «версии» до его текущего состояния. Если этот объект домена имеет большое количество атрибутов, это означает, что каждое изменение требует вставки новой строки в соответствующую таблицу (не обновление, потому что история будет потеряна, а вставка). Допустим, этот объект домена является человеком, и у меня есть 500 000 человек, которые отслеживают в среднем более 100 изменений в течение жизненного цикла людей с различными атрибутами. Соедините это с тем фактом, что редко встречается приложение, имеющее только 1 основной объект домена, и вы быстро догадаетесь, что размер базы данных быстро выйдет из-под контроля.

Простым решением является сохранение только разностных изменений в основных объектах домена, а не повторное сохранение избыточной информации.

Все модели меняются со временем, чтобы отразить новые потребности бизнеса. Период. Использование EAV - это всего лишь один из инструментов в нашей коробке; но это никогда не должно автоматически классифицироваться как «плохое».

Джерри Джасперсон
источник
2
+1 для «Использование EAV - это всего лишь один из инструментов в нашей коробке, но он никогда не должен автоматически классифицироваться как« плохой »».
Catchops
Кстати, это называется SCD (медленно меняющиеся размеры). Также битемпоральные требования (особый случай SCD типа 4) требуют схемы EAV для атрибутов, которые имеют это свойство. Помните, что 99% NoSQL не имеет нативных объединений, поэтому, если вам нужны «живые» объединения с этим типом данных, EAV - единственный путь.
Cowbert
3

Я борюсь с той же проблемой. Возможно, вам будет интересно проверить следующее обсуждение двух существующих решений для электронной коммерции: Magento (EAV) и Joomla (обычная реляционная структура): https://forum.virtuemart.net/index.php?topic=58686.0

Похоже, что EAV-производительность Magento - настоящая демонстрация.

Вот почему я склоняюсь к нормализованной структуре. Чтобы преодолеть недостаток гибкости, я думаю о том, чтобы в будущем добавить отдельный словарь данных (XML или отдельные таблицы БД), который можно редактировать, и на этом основании код приложения для отображения и сравнения категорий продуктов с новым набором атрибутов будет генерируется вместе с SQL-скриптами.

Такая архитектура в данном случае, кажется, самая приятная вещь - гибкая и производительная одновременно.

Проблема может заключаться в частом использовании ALTER TABLE в реальных условиях. Я использую Postgres, так что его MVCC и транзакционный DDL, надеюсь, облегчат боль.

aaimnr
источник
2

Я все еще голосую за моделирование на самом низком значимом атомном уровне для EAV. Позвольте стандартам, технологиям и приложениям, которые ориентированы на определенное сообщество пользователей, решать модели контента, повторяющиеся потребности атрибутов, зерен и т. Д.

Аманда Сюй
источник
2

Если речь идет только об атрибутах каталога продуктов и, следовательно, требования к проверке этих атрибутов довольно ограничены, единственным реальным недостатком EAV является производительность запросов, и даже это проблема, только когда ваш запрос имеет дело с несколькими «вещами» (продуктами) с атрибутами, производительность для запроса "дай мне все атрибуты для продукта с идентификатором 234", хотя и неоптимальная, все еще достаточно быстра.

Одно из решений состоит в том, чтобы использовать базу данных SQL / модель EAV только для стороны администрирования / редактирования каталога продуктов и иметь некоторый процесс, который денормирует продукты в нечто, что делает их доступными для поиска. Поскольку у вас уже есть атрибуты и, следовательно, весьма вероятно, что вы хотите получить огранку, это может быть Solr или ElasticSearch. Этот подход позволяет избежать практически всех недостатков модели EAV, а дополнительная сложность ограничена сериализацией всего продукта в JSON при обновлении.

боб
источник
2

EAV имеет много недостатков:

  1. Снижение производительности с течением времени Как только объем данных в приложении становится больше определенного размера, поиск и обработка этих данных, вероятно, станут все менее и менее эффективными.
  2. SQL-запросы очень сложны и трудны для написания.
  3. Проблемы целостности данных. Вы не можете определить внешние ключи для всех необходимых полей.
  4. Вы должны определить и поддерживать свои собственные метаданные.
Габриэль Войнеа
источник
1. Это верно и для большинства реляционных баз данных; Вот почему был изобретен шардинг. 2. Моделирование данных может быть сложным и трудным для реализации. Я провел недели-месяцы в ожидании изменений схемы куба OLAP. 3. Уже в основном это делается в программном обеспечении. 4. Вы должны делать это «в ERwin, Excel и Visio» при моделировании реляционной схемы.
ковбер
1

У меня немного другая проблема: вместо множества атрибутов с разреженными значениями (что, возможно, является хорошей причиной для использования EAV), я хочу сохранить нечто более похожее на электронную таблицу. Столбцы на листе могут меняться, но внутри листа все ячейки будут содержать данные (не разреженные).

Я сделал небольшой набор тестов для сравнения двух проектов: один с использованием EAV, а другой с использованием Postgres ARRAY для хранения данных ячеек.

EAV введите описание изображения здесь

массив введите описание изображения здесь

Обе схемы имеют индексы для соответствующих столбцов, и индексы используются планировщиком.

Оказалось, что основанная на массиве схема была на порядок быстрее как для вставок, так и для запросов. Из быстрых тестов оказалось, что оба масштабируются линейно. Однако тесты не очень тщательные. Предложения и вилки приветствуются - они под лицензией MIT.

z0r
источник
как вы делали соединения в столбцах листа (т.е. vlookup) с моделью массива? Разве вам не нужно писать собственную функцию сортировки слиянием массивов? Сильно сомневаюсь, что это может быть так же хорошо, как и скомпилированная сортировка слиянием, если вы использовали sheet_id + x-координата + y-координата ячейки в качестве ключа значения ячейки. (чтобы эмулировать Excel, предварительно сгенерируйте таблицу поиска для x-координат, где 0-18278 - столбцы A-ZZZ (Excel достигает максимума в 16384)), затем вы можете выбрать значения, где sheet_id = uuid и x-координат = 0 и y-координаты <1001, чтобы получить первые 1000 рядов
полковника
@cowbert ты прав; на самом деле я просто загружаю интересующие меня столбцы и делаю соединение в Python. Отними!
z0r