EAV против сериализованного объекта против SQL с Xpath?

#sql #database-design #doctrine-orm

#sql #проектирование базы данных #doctrine-orm

Вопрос:

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

Эти метаданные являются переменными и устанавливаются «на лету».

Пример метаданных :

  • commentCount
  • hasCompletedProfile
  • isActiveMember

и т.д. Позже я хотел бы добавить hasGravatar метаданные, по этой причине я не могу легко спроектировать и нормализовать таблицу.

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

В настоящее время я знаю три варианта, даже если я не знал ни одного из них.

  • EAV
  • Сериализованные объекты
  • Поле XML (я где-то читал, что можно хранить XML в столбце и использовать XPATH или что-то еще для запроса данных)

Похоже, что у всех этих опций есть плюсы и минусы, но поскольку я никогда с ними не экспериментировал, я действительно не знаю, какие именно.

У вас есть какие-либо отзывы или советы?

В настоящее время я работаю с Zend Framework и Doctrine 2 с сервером MySQL

Ответ №1:

XML и сериализованные объекты очень похожи, поскольку вы, вероятно, будете использовать 1 столбец для хранения этих произвольных данных. Это быстро становится очень запутанным, и его трудно легко отличить в предложениях SQL WHERE (хотя некоторые СУБД поддерживают XPath)

EAV, с другой стороны, предоставит отдельную строку для каждой Key => Value имеющейся у вас пары, которую вы можете легко извлечь с помощью объединения или подзапроса. Основным недостатком является то, что это может привести к снижению производительности, если у вас здесь много данных. Другим недостатком является то, что для упрощения вы должны хранить все ключи / значения в виде текста в БД. Вы могли бы создать таблицу EAV для каждого типа, но в большинстве языков это практически не требуется, поскольку то, что вы извлекаете, получается в виде строки или может быть преобразовано туда в любом случае. Простое сохранение конфигурации пользователя / свойств должно быть идеально подходящим для EAV.

Итак, у вас может быть таблица user_metadata с 3 полями:

 metadata_id INTEGER
user_id INTEGER
key CHAR
value CHAR
  

Затем вы могли бы получить все эти данные сразу для пользователя:

 SELECT * FROM user_metadata WHERE metadata_user_id = $user_id
  

Или вы могли бы извлекать отдельные метаданные вместе с вашими пользовательскими данными

 SELECT user.*, meta_gravatar.value AS hasGravatar
FROM user
LEFT JOIN user_metadata AS meta_gravatar
 ON meta_gravatar.user_id = user.user_id AND meta_gravatar.key = 'hasGravatar'
WHERE user.user_id = $user_id
  

Ответ №2:

EAV: Это сложно и медленно. Это пример того, как не использовать базу данных SQL. У вас не может быть индекса свойств в EAV, и вам нужна некоторая нетривиальная логика, чтобы перенести данные из базы данных в объекты бизнес-логики. Кроме того, ваши SQL-запросы становится трудно оптимизировать.

Сериализованные объекты: сериализация часто зависит от языка или платформы. Невозможно создать индекс для какого-либо свойства или выполнить поиск по чему-либо, но это простой способ хранить данные неопределенной структуры.

Поле XML: Использование стандартизированного представления лучше, чем сериализация. Кроме того, на вашем SQL Server может быть поддержка таких структур данных.

Поле JSON: то же, что и поле XML, однако JSON поддерживает примитивные типы данных (int, bool, null), и его быстрее и проще анализировать и сериализовать, чем XML. Некоторые серверы SQL также предоставляют некоторую поддержку для этого.

Все три способа сериализации имеют один и тот же недостаток: нет индексов в свойствах. В большинстве приложений это приемлемо, поскольку данные в любом случае не обрабатываются базой данных, поэтому они являются просто большим двоичным объектом для приложения. Хорошо то, что этот большой двоичный объект не усложняет схему базы данных и операции.

Есть еще один способ реализовать такую альтернативу EAV: обычная старая таблица SQL. Если новое свойство требует некоторых изменений в коде приложения, вы также можете добавить столбец SQL. Если у вас есть пользовательский интерфейс и логика приложения для определения свойств во время выполнения, вы можете научить свое приложение использовать запросы ALTER TABLE. Затем вы просто добавляете или удаляете столбцы по мере необходимости. В конце концов, это будет намного проще и эффективнее, чем внедрение EAV, если у вас есть хороший конструктор запросов.