Хорошо, это модель ER того, что у вас есть в настоящее время (без учета количества элементов):
![](https://i.stack.imgur.com/uQH0U.png)
Теперь давайте сосредоточимся на Календаре и SubCalendar.Очевидно, у вас есть иерархия там.Но как иерархии превращаются в таблицы?Есть три распространенных способа сделать это:
1) Убить родителя и оставить потомков : в этом случае вы удаляете родительский объект и отправляете все поля из этого объекта каждому изребенок.В вашем примере у вас есть только один дочерний элемент, поэтому все атрибуты родительского элемента будут идти только к нему.
Преимущества : Нет нулевых значений, поскольку каждая таблица будет иметь все, что ей нужно.Никаких объединений не требуется.Если вы будете выполнять запросы для поиска только одного типа дочерних элементов, эта схема будет полезна, поскольку вам не нужно будет фильтровать по типу, поскольку в каждой таблице будет храниться только один тип
Недостатки :Эта схема не подходит для случаев, когда у вас есть перекрывающиеся дочерние элементы.Другими словами, если родительская строка может иметь более одного дочернего элемента при отправке полей каждому дочернему элементу, родительские данные будут дублироваться в каждом дочернем элементе.Не хорошо, так что не используйте эту стратегию, если это так.Кроме того, если у вас много дочерних элементов и очень мало записей в каждой, у вас будет много таблиц с несколькими записями в каждой, поэтому управлять им может быть немного сложнее
![](https://i.stack.imgur.com/j3NnY.png)
2) Убить детей и сохранить родителя : в этом случае вы удаляете всех детей и отправляете все их атрибуты родителю.Поскольку родитель является смесью себя и всех своих потомков, ему нужен способ определить, к какой строке принадлежит какой тип потомков.Это достигается добавлением нового атрибута в родительский объект, который будет определять тип каждой строки (независимо от типа данных).
Преимущества : будет только одна таблица для всехдети, так что легко управлять.Нет присоединений не требуется.Может быть полезно, если большинство запросов, выполняемых к этой таблице, требуют результатов от более чем одного типа дочерних элементов.
Недостатки : Опять же, если родитель может иметь строку, относящуюся кданные одного дочернего элемента будут дублироваться, поскольку для каждого из них будет по одной строке, поэтому в этом решении есть ограничение.Кроме того, новый столбец должен быть добавлен в качестве метаданных.Объем записей в таблице будет больше.Нулевые значения должны быть присвоены данным, которые есть у детей, а также у родителей или других детей.
![](https://i.stack.imgur.com/o5MZN.png)
3) Сохранить все : наименее кровавыйрешение не состоит в том, чтобы убивать что-либо :) В этом случае иерархия заменяется отношениями между родителем и каждым из детей.Таким образом, ребенок должен будет присоединиться к родительской таблице с помощью внешнего ключа для доступа к данным родителя.
Преимущества : нет ни дублирования данных, ни нулевых значений.Каждый объект имеет только минимальный объем данных, а остальные могут быть получены путем присоединения к родительской таблице.В этом случае родительская строка может быть связана с несколькими дочерними элементами без дублирования данных.Если будет выполнено много запросов, которые могут быть удовлетворены только одной таблицей (обычно родительской), это хороший вариант.Еще одна вещь заключается в том, что легко расширить на большее количество календарей, например, если нужно добавить новый календарь, требующий новых полей, то нужно добавить новую таблицу, не изменяя текущие
Недостатки : Требуется большинство таблиц (фактически на одну больше, чем первая).Соединение необходимо для каждого дочернего элемента, что ухудшает производительность по мере увеличения набора данных.Кроме того, внешние ключи будут необходимы для объединения обеих таблиц.Если для большинства запросов требуются данные от родителей и потомков, эта схема будет худшей с точки зрения производительности
![](https://i.stack.imgur.com/gk7N8.png)
Теперь вы спросили, какая схема базы данных best
.Я думаю, что теперь ясно, что это зависит от требований, типов запросов, которые будут выполняться, структуры данных и т. Д.
Однако я могу проанализировать это немного подробнее.Вы сказали, что у вас есть таблица календаря, и иногда требуется больше данных для одного из них.Таким образом, мы можем сказать, что у нас есть 2 типа календарей, родитель и ребенок.Таким образом, мы могли бы подумать, что переход к решению 2 - хорошая возможность, потому что у вас будет 2 строки, представляющие каждый тип, но мы были бы неправы.Это потому, что каждый ребенок включает в себя своего родителя в этом случае.Теперь, если мы можем предположить, что если SubAttribute
всегда будет ненулевым для дочернего элемента и нулевым для родителя, мы можем даже удалить CalendarType
, что фактически приведет к решению 1.
Наконец, какпрактическое правило (и в основном потому, что большинство запросов имеют много объединений в реальной жизни), если вы хотите сосредоточиться на производительности, вы должны пойти на решение 1, в противном случае, если вы хотите сосредоточиться на нормализованном дизайне, вы должны пойти на решение3.
Надеюсь, это очистило некоторые сомнения и, возможно, породило другие:)