EAV - гибридный плохой выбор дизайна базы данных

Мы должны перепроектировать устаревшую базу данных POI от MySQL до PostgreSQL. В настоящее время все объекты имеют атрибуты 80-120 +, которые представляют индивидуальные свойства.

Мы попросили рассмотреть гибкость, а также хороший подход к разработке новой базы данных. Однако новый дизайн должен позволять:

  • n нет. атрибутов/свойств для любого объекта, то есть никаких атрибутов для любого объекта не являются фиксированными и могут меняться на регулярной основе.

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

Существует довольно много дискуссий о проблемах с производительностью EAV, но если мы не будем использовать гибридный EAV, мы закончим:

  • имея много пустых столбцов (мы по-прежнему добавляем новые столбцы, даже если 99% данных не имеют этих свойств)
  • тратить больше времени на поддержку базы данных. когда атрибуты продолжают меняться.
  • не позволяет админам контента добавлять новые свойства к существующим объектам.

В любом случае, что мы думаем о новом дизайне (включая базовый ERD):

  • Имеют отдельные таблицы для каждого объекта, содержащего некоторую базовую информацию, которая является эксклюзивной, например. id, имя, адрес, контакт, созданный и т.д.

  • Имейте тип атрибута 2 атрибута и атрибут для хранения информации о свойствах.

  • Свяжите каждую сущность с атрибутом, используя отношение "многие-ко-многим".

  • Сохранять адреса в другой таблице и ссылаться на сущности, используя внешний ключ.

alt text

Мы думаем, что это позволит нам быть более гибкими при добавлении, удалении или обновлении свойств.

Эта конструкция, однако, приведет к увеличению числа соединений при извлечении данных, например, для отображения всех "атрибутов" для данного стадиона у нас может быть запрос с 20 + объединениями для извлечения всех связанных атрибутов в одной строке.

Каковы ваши мысли об этом дизайне, и каковы будут ваши советы по его улучшению.

Спасибо, что прочитали.

Ответы

Ответ 1

Я поддерживаю 10-летнюю систему, у которой есть центральная модель EAV с объектами 10M +, значениями 500M + и сотнями атрибутов. Некоторые соображения дизайна из моего опыта:

Если у вас есть какая-либо бизнес-логика, применимая к определенному атрибуту, то стоит использовать этот атрибут как явный столбец. Атрибуты EAV должны быть действительно универсальными, приложение не должно отличать атрибут A от атрибута B. Если вы находите литеральную ссылку на атрибут EAV в коде, то вероятность того, что он должен быть явным столбцом.

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

  • У вас есть соглашения и правила, которые позволяют вам узнать, какая часть вашего приложения читает и изменяет часть данных.
  • Используйте представления, чтобы облегчить поиск файлов базы данных с помощью инструментов отладки.
  • Создавайте и поддерживайте генераторы тестовых данных, чтобы вы могли легко создавать соответствующие фиктивные данные для тех частей модели, которые вас сейчас не интересуют.
  • Используйте строгий контроль версий баз данных. Единственный способ сделать изменения схемы должен быть с помощью инструмента, который отслеживает и применяет сценарии изменений. Postgresql имеет транзакционный DDL, то есть одну функцию убийцы для автоматизации изменений схемы.

Postgresql не очень нравится тощие таблицы. Каждое значение атрибута приводит к 32 байтам служебных данных для хранения данных в дополнение к дополнительной работе по перемещению всех строк для совместного использования данных. Если вы в основном читаете и записываете атрибуты в виде пакета, рассмотрите сериализацию данных в строке каким-либо образом. attr_ids int[], attr_values text[] - один из вариантов, hstore - это другая или какая-то клиентская сторона, например json или protobuf, если вам не нужно касаться каких-либо конкретных данных на стороне базы данных.

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

Всегда помните, что код - это данные, а данные - код. Вам нужно найти правильный баланс между толканием решений в метамодель и выражением их в качестве кода. Если вы сделаете метамодель слишком много, для его модификации потребуется такая же способность понимать систему, инструменты управления версиями, процедуры QA, как ваш код, но у него не будет ни одного инструмента. По сути, вы будете программировать на очень неудобном нестандартном языке. С другой стороны, если вы оставите слишком много кода, для каждого тривиального изменения потребуется новая версия вашего программного обеспечения. Люди склонны ошибаться в сторону слишком сложной метамодели. Создание инструментов разработчика для метамоделей - тяжелая и утомительная работа и имеет ограниченную выгоду. С другой стороны, сделать процесс выпуска более дешевым, автоматизируя все, что происходит от фиксации для развертывания, имеет много преимуществ.

Ответ 2

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

Я думаю, что "сущность" немного выше общего. Кажется, у вас есть представление о том, что должно быть связано с этим сущностью, например, адресом и контактом. Что делать, если вы решите иметь "Книги" в модели. Будут ли у них также адреса и контакты? Я думаю, вы должны попытаться найти правильные обобщения и сохранить части EAV модели в минимерии. Всякий раз, когда вы обнаруживаете, что хотите показать определенный поднабор атрибутов или проверить наличие ценности или определить поведение, основанное на значении, которое вы действительно должны его моделировать как столбцы.

У вас не будет лучшей возможности для разработки этой системы, чем сейчас. Требования известны с предыдущей версии, а также то, что сработало, а что нет. (Просто не становитесь жертвой Второго эффекта системы)

Ответ 3

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

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

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

Ответ 4

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

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