#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, если у вас есть хороший конструктор запросов.