Какова лучшая схема базы данных для поддержки значений, которые соответствуют только определенным строкам? - PullRequest
13 голосов
/ 31 декабря 2011

У меня есть таблица базы данных с именем Календарь с полями

  1. Id (PK)
  2. Имя
  3. Описание
  4. CalendarTypeId (FK в CalendarType таблица)

У меня есть другая таблица с именем CalendarType с полями

  1. Id (PK)
  2. Имя
  3. Описание

Проблема в том, что мне нужно хранить дополнительное поле для каждого календаря, где тип календаря равен 2. (но это поле будетне имеет значения для любого другого типа календаря).

Должен ли я просто создать новое поле в таблице Calendar и игнорировать это поле для всех других календарей, имеющих другой calendarTypeid или есть лучший способорганизовать эту схему для поддержки этой необходимости.

Ответы [ 5 ]

15 голосов
/ 27 февраля 2012

Хорошо, это модель ER того, что у вас есть в настоящее время (без учета количества элементов):

Теперь давайте сосредоточимся на Календаре и SubCalendar.Очевидно, у вас есть иерархия там.Но как иерархии превращаются в таблицы?Есть три распространенных способа сделать это:

1) Убить родителя и оставить потомков : в этом случае вы удаляете родительский объект и отправляете все поля из этого объекта каждому изребенок.В вашем примере у вас есть только один дочерний элемент, поэтому все атрибуты родительского элемента будут идти только к нему.

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

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

2) Убить детей и сохранить родителя : в этом случае вы удаляете всех детей и отправляете все их атрибуты родителю.Поскольку родитель является смесью себя и всех своих потомков, ему нужен способ определить, к какой строке принадлежит какой тип потомков.Это достигается добавлением нового атрибута в родительский объект, который будет определять тип каждой строки (независимо от типа данных).

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

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

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

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

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

Теперь вы спросили, какая схема базы данных best.Я думаю, что теперь ясно, что это зависит от требований, типов запросов, которые будут выполняться, структуры данных и т. Д.

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

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

Надеюсь, это очистило некоторые сомнения и, возможно, породило другие:)

5 голосов
/ 31 декабря 2011

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

Однако вы явно не указали, варьировалось ли значение дополнительного поля для каждого экземпляра Календаря с typeID, равным 2. Иногда в моих таблицах типов есть поля подтипов и т. Д., Но я предполагаю, что это тот случай, когдаэкземпляры Calendar типа 2 будут иметь разные значения в обязательном поле.

4 голосов
/ 04 марта 2012

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

Это просто, и, прежде всего, его легко проверить.

Я мог бы немного ослабить этот ответ (не самый эффективный)возможно), но это полностью зависит от масштаба вашего решения.Реальность такова, что эти ограничения вполне могут измениться в ближайшие пару месяцев, и вы не хотите заглядывать в угол, выбирая «правильный» путь, когда вы еще не знаете, что это такое.Вполне возможно, что когда вы дойдете до 10-го типа календаря, появится шаблон, который действительно подскажет вам лучший (или самый обычный) способ сделать это.А пока, просто сделайте это простым и сделайте его легко тестируемым и легко изменяемым позже.

2 голосов
/ 27 февраля 2012

Леора,

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

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

Стивен

2 голосов
/ 31 декабря 2011

Вы можете использовать шаблон наследования одной таблицы, который близок к вашему предложению,

http://martinfowler.com/eaaCatalog/singleTableInheritance.html

или

http://martinfowler.com/eaaCatalog/classTableInheritance.html

если вы хотите специализировать некоторые таблицы для соответствия типам (Calendar и CalendarType2), которые вы пытаетесь представить в своей базе данных

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...