Проектирование баз данных: гибкость по сравнению с простотой

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

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 мог быть вздором или blah_blah.

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

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

7
задан Den 27 August 2015 в 14:39
поделиться

6 ответов

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

Вариант №2 называется EAV - Entity Attribute Value - и у него есть несколько серьезных недостатков - см.

10
ответ дан 6 December 2019 в 09:18
поделиться

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

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

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

3
ответ дан 6 December 2019 в 09:18
поделиться

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

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

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

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

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

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

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

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

2
ответ дан 6 December 2019 в 09:18
поделиться

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

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

  1. Убедитесь, что вы не создаете EAV для всего. Он нужен только для "неизвестных предметов".
  2. Помните, что у EAV нет отношений "ключ-иностранец", от которых можно зависеть.
  3. Производительность низкая из-за нетривиальных запросов, а обслуживание может быть больше.
  4. Помните, что EAVs должен быть повернут, чтобы сделать его значимым (ну, чаще всего).
3
ответ дан 6 December 2019 в 09:18
поделиться

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

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

Вариант №2 Используйте этот вариант, когда сущность X не может быть полностью определена, т.е. вы не знаете, какой набор атрибутов необходим для ее "полного" определения.

Для примера возьмем запись о сотруднике, как указано в статье "Five simple database design errors you should avoid" [ссылка предоставлена @marc_s]. Да!!! у вас возникнет соблазн выбрать вариант 1, но если рассмотреть случай сотрудников, работающих в крупных организациях, то после единичной записи информация о сотруднике - как ее определение, так и содержание - очень динамична, и требуется комбинация варианта №1 и варианта №2.

1
ответ дан 6 December 2019 в 09:18
поделиться

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

0
ответ дан 6 December 2019 в 09:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: