Дизайн базы данных: гибкость и простота - PullRequest
7 голосов
/ 25 июня 2010

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

1.

CREATE TABLE x (
    my_id INT PRIMARY KEY,
    ...,
    text_attribute_blah TEXT,
    text_attribute_blah_blah TEXT
);

против

2.

CREATE TABLE x (
    my_id INT PRIMARY KEY,
    ...
)

CREATE TABLE attributes (
    my_id INT,  /* foreign key to x.my_id */
    text_attribute_type INT,
    text_attribute TEXT
)

Где attribute_type может быть бла или бла_бла.

Вариант 1 предлагает простоту - таблицу легче читать / писать; Вариант 2 обеспечивает гибкость (если мы хотим добавить еще один атрибут, такой как blah_blah_blah, нам не нужно вносить изменения в схему и, следовательно, меньше изменений кода).

Есть ли правильный / неправильный ответ на эту загадку? Один из этих вариантов считается лучшей практикой, чем другие? Можете ли вы указать мне на дальнейшее чтение, которое может помочь определить путь вперед?

Ответы [ 7 ]

10 голосов
/ 25 июня 2010

Я почти всегда выбираю # 1 - я просто предпочитаю иметь атрибуты в качестве столбцов в моих таблицах - делает запросы, индексацию для производительности и общую обработку намного проще и прозрачнее.

опция # 2называется EAV - Значение атрибута объекта - и у него есть несколько существенных недостатков - см.

3 голосов
/ 25 июня 2010

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

Сказав это, EAV имеют множество проблем.При правильном использовании, IMO, они полезны.

  1. Убедитесь, что вы не создаете EAV для всего.Это только для «неизвестных элементов».
  2. Помните, что EAV не имеют отношений внешнего ключа, от которых зависит.
  3. Производительность низкая из-за нетривиальных запросов, и обслуживание может быть больше.
  4. Имейте в виду, что EAV необходимо поворачивать, чтобы сделать его осмысленным (ну, чаще всего).
3 голосов
/ 25 июня 2010

Интересно, что вы не упоминаете ни о производительности, ни о целостности данных. Для чего стоит модель # 1 - лучший подход для этих соображений.

Гибкость значительно переоценена в отношении моделей данных. Большинство структур таблиц хорошо известны в начале разработки и остаются стабильными в течение всего срока службы базы данных. Если у вас есть приложение, в котором модель действительно гибкая и непостижимая, то, вероятно, вам вообще не следует использовать СУБД. Вместо этого выберите один из продуктов NoSQL.

Так что это еще один голос за № 1.

2 голосов
/ 25 июня 2010

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

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

Если вы работаете с упакованным приложением, которое вы хотите настроить для своих клиентов, у вас есть три широких подхода.

  1. Структура EAV, аналогичная варианту 2. Это гибкий, но неэффективный запрос, особенно если запросы становятся сложными с несколькими объединениями.

  2. Создайте набор полей «Пользователь» (Пользователь1, Пользователь2 и т. Д.) В таблицах. Это ограничивает вас конечным числом, но оно может быть довольно большим (вы можете иметь User01-User99, если хотите). Тем не менее, это самый эффективный и простой запрос. Другой недостаток в том, что поля несколько непрозрачны. Вы должны иметь доступ к информации о конфигурации, чтобы знать значение «User3». Это также жертвует некоторой безопасностью типа. В целом, однако, ваш механизм пользовательских полей будет иметь некоторые свои собственные метаданные и какую-то общую структуру, поэтому некоторая безопасность этого типа может быть обеспечена с помощью этого.

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

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

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

1 голос
/ 03 сентября 2010

@ marc_s

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

Вот пример из финансовой области.

Если вы хотите получить все атрибуты сделки, это зависит от типа инструмента.Намного легче захватить большинство Forex, Money Market и даже облигационных инструментов, поскольку они очень структурированы.Но по мере продвижения к производным продуктам это становится очень громоздким.Они очень экзотичны по своей природе и постоянно меняются с точки зрения структуры (отсюда и ее значение и т. Д.).Чтобы получить такую ​​динамически изменяющуюся информацию, мы должны выбрать EAV.Конечно, делая этот выбор, нужно помнить, что он приносит много негативов, перечисленных выше в вашем комментарии.

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

Шрини

1 голос
/ 25 июня 2010

@ marc_s Я не верю, что можно «почти всегда» сделать какой-либо один выбор среди вышеупомянутых вариантов. Есть случай, чтобы поддержать оба решения.

Вариант № 1 Пойдите на это, когда сущность X хорошо определена, то есть вы точно знаете, что вам нужно захватить, чтобы определить X. В таком случае одна единственная запись X в значительной степени захватывает все, что обозначает экземпляр X.

Вариант № 2 Сделайте это, когда такая сущность X не может быть полностью определена, т. Е. Вы не знаете, какие атрибуты набора требуются для ее «полного» определения.

Например, возьмите пример записи о сотруднике, упомянутой в статье «Пять простых ошибок проектирования базы данных, которых следует избегать» [ссылка предоставлена ​​@marc_s]. Да!!! у вас будет соблазн получить вариант 1, но если вы рассмотрите случай сотрудников, работающих в крупных организациях, один раз запишите информацию о сотрудниках - и ее определение, и содержание являются очень динамичными, и требуется сочетание варианта № 1 и варианта № 2.

0 голосов
/ 25 июня 2010

Как было сказано ранее, это зависит от ваших требований.Вы должны выбрать # 2, только если вам нужно, например, добавить новые типы атрибутов как часть рабочего процесса вашей программы.Делать это с добавлением новых столбцов в ваши таблицы, безусловно, хуже, чем иметь одну дополнительную таблицу и одно дополнительное объединение в ваших запросах.

...