Ответ 1
Хорошо, это ER-модель того, что у вас есть (отсутствие мощности):
Теперь давайте сосредоточимся на Календаре и SubCalendar. Ясно, что у вас есть иерархия. Но как иерархии превращаются в таблицы? Существует три общих способа сделать это:
1) Убить родителя и сохранить детей. В этом случае вы удаляете родительский объект и отправляете все поля из этого объекта каждому из этих детей. В вашем примере у вас есть только один ребенок, поэтому все родительские атрибуты будут доступны только для него.
Преимущества: Нет нулевых значений, так как каждая таблица будет иметь все необходимое. Никаких объединений не требуется. Если вы будете запускать запросы только для одного типа детей, эта схема будет полезна, потому что вам не нужно будет фильтровать по типу, потому что каждая таблица будет хранить только один тип
Недостатки: эта схема не подходит для случаев, когда у вас есть перекрывающиеся дети. Другими словами, если родительская строка может иметь более одного ребенка при отправке полей каждому ребенку, родительские данные будут дублироваться у каждого ребенка. Нехорошо, поэтому не используйте эту стратегию, если это так. Кроме того, если у вас много детей и очень мало записей в каждом, у вас будет много таблиц с несколькими записями каждый, так что может стать немного сложнее управлять
2) Убить детей и сохранить родительский. В этом случае вы удаляете все дочерние элементы и отправляете все свои атрибуты родителям. Поскольку родитель теперь представляет собой смесь самого себя и всех своих детей, ему нужен способ определить, какая строка принадлежит тому типу детей. Это достигается добавлением нового атрибута к родительскому объекту, который будет определять тип каждой строки (независимо от типа данных).
Преимущества: для всех детей будет только одна таблица, поэтому ее легко управлять. Никаких объединений не требуется. Может быть полезно, если большинство запросов, которые выполняются в этой таблице, требуют результатов от более чем одного типа детей.
Недостатки: Опять же, если родитель может иметь строку, относящуюся к нескольким дочерним данным, будет дублироваться, так как для каждой из них будет одна строка, поэтому в этом решении есть ограничение. Кроме того, новый столбец должен быть добавлен в метаданные. Объем записей в таблице будет больше. Нулевые значения должны быть привязаны к данным, которые есть у детей, и родителям или другим детям.
3) Сохранить все: наименее кровавое решение - не убить ничего:) В этом случае иерархия заменяется отношением между родителем и каждым из них. Таким образом, дочерний элемент должен будет подключиться к родительской таблице с помощью внешнего ключа для доступа к родительским данным.
Преимущества: Нет дублирования данных или нулевых значений. Каждый объект имеет только минимальный объем данных, а остальное можно получить, присоединившись к родительской таблице. В этом случае родительская строка может быть связана с несколькими детьми без дублирования данных. Если будет запущено много запросов, которые могут быть удовлетворены только одной таблицей (обычно родительской), это хороший вариант. Еще одна вещь заключается в том, что ее можно легко расширить до большего количества календарей, например, если нужно добавить новый календарь, который требует новых полей, то необходимо добавить новую таблицу без изменения текущих
Недостатки: Требуется большинство таблиц (на самом деле один больше первого). Для каждого ребенка требуется соединение, которое ухудшит производительность, чем больше набор данных. Кроме того, для соединения обеих таблиц потребуются внешние ключи. Если для большинства запросов потребуются данные от родителей и детей, эта схема будет наихудшей с точки зрения производительности
Теперь вы спросили, какая схема базы данных best
. Я думаю, теперь ясно, что это зависит от требований, типов запросов, которые будут выполняться, способа структурирования данных и т.д.
Однако, я могу проанализировать это немного больше. Вы сказали, что у вас есть таблица календаря, и иногда для каждого из них требуется больше данных. Итак, мы можем сказать, что у нас есть 2 типа календарей, родитель и ребенок. Поэтому мы можем подумать, что переход на решение 2 - хорошая возможность, потому что у вас будет 2 строки, представляющие каждый тип, но мы ошибались. Это связано с тем, что в этом случае каждый ребенок включает в себя родителя. Теперь, если мы можем предположить, что если SubAttribute
всегда будет непустым для дочернего элемента и null для родителя, мы даже удалим CalendarType
, что фактически приведет к решению 1.
Наконец, как правило (главным образом потому, что большинство запросов имеют много объединений в реальной жизни), если вы хотите сосредоточиться на производительности, вы должны пойти на решение 1, в противном случае, если вы хотите сосредоточиться на нормализации вы должны пойти на решение 3.
Надеюсь, это устранило некоторые сомнения и, возможно, вызвало другие:)