Моделирование базы данных - концептуально разные объекты с почти одинаковыми полями - PullRequest
1 голос
/ 19 марта 2010

Предположим, у вас есть два набора концептуальных сущностей:

  • MarketPriceDataSet с несколькими ForwardPriceEntries
  • PoolPriceForecastDataSet , который имеет несколько PoolPriceForecastEntry

Оба разных дочерних объекта имеют почти одинаковые поля:

ForwardPriceEntry имеет

  • StartDate
  • EndDate
  • SimulationItemId
  • ForwardPrice
  • MarketPriceDataSetId (внешний ключ к родительской таблице)

PoolPriceForecastEntry имеет

  • StartDate
  • EndDate
  • SimulationItemId
  • ForecastPoolPrice
  • PoolPriceForecastDataSetId (внешний ключ к родительской таблице)

Если бы я смоделировал их как отдельные таблицы, единственным отличием был бы внешний ключ и имя поля цены.

Был спор о том, следует ли объединять две почти идентичные таблицы в одну.

Опции, о которых я думал, чтобы смоделировать это:

  • Просто держите их как две независимые таблицы
  • Имейте оба набора в одной таблице с дополнительным полем типа, и parent_id , равный внешнему ключу любой родительской таблице. Это принесет в жертву проверки ссылочной целостности.
  • Имейте оба набора в одной таблице с дополнительным полем типа и создайте сложную последовательность объединения таблиц для поддержания ссылочной целостности.

Как вы думаете, что я должен делать и почему?


Другая информация, которая может иметь или не иметь отношение к делу:

  • Два набора данных слабо связаны: один набор каждого будет загружен в память для пакетной обработки, а иногда набор PoolPriceForecastEntries будет создан путем копирования из ForwardPriceEntries .

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

Ответы [ 4 ]

3 голосов
/ 19 марта 2010

«Был спор о том, следует ли объединять две почти идентичные таблицы в одну».

Есть ли там?

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

3 голосов
/ 19 марта 2010

Очень часто в описанной вами ситуации моделируемый предмет соответствует шаблону, называемому «специализация обобщения». Тот факт, что два предыдущих ответа обсуждают подтипы, подтверждает это. Объектная модель имеет тенденцию иметь дело с gen-spec, используя подтипы и наследование.

Реляционная модель также может иметь дело с gen-spec, но она немного сложнее и обычно не преподается в учебниках для начинающих. У вас есть несколько таблиц, по одной для каждого подтипа, содержащих ключевые и неключевые атрибуты, которые свойственны подтипу. Данные, относящиеся к супертипу и наследуемые всеми подтипами, как правило, объединяются в одну таблицу.

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

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

1 голос
/ 19 марта 2010

Поскольку у сущностей столько общих атрибутов, вы можете думать о них как о подтипах.

Логически у вас будет супертип PriceEntry и подтипы ForwardPriceEntry и PoolPriceForecastEntry. Один вопрос, на который нужно ответить, будет ли цена общей для супертипа. Я предполагаю, что это так.

Теперь вопрос в том, как физически реализовать подтип. Есть 3 подхода, которые вы можете использовать:

  1. Создать таблицу для каждого подтипа (свертывание)
  2. Создание единой таблицы со всеми атрибутами (сведение)
  3. Создать одну таблицу супертипа и таблицу подтипов для каждого подтипа (Identity)

У каждого из этих подходов есть свои плюсы и минусы. Для обсуждения плюсов и минусов каждого подхода см. Получение физического с подтипами .

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

Таблица PriceEntry может выглядеть следующим образом:

PriceEntryId (PK)
PriceEntryTypeCode (NN)
StartDate (NN)
EndDate 
SimulationItemId (NN)
Price (NN)
MarketPriceDataSetId (FK)
PoolPriceForecastDataSetId (FK)

Вы по-прежнему можете применять FK в столбцах MarketPrice и PoolForecast. Вы также можете добавить ограничение проверки уровня таблицы, чтобы гарантировать заполнение хотя бы одного из FK.


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

0 голосов
/ 19 марта 2010

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

  • StartDate
  • EndDate
  • SimulationItemId
  • ForwardPrice
  • MarketPriceDataSetId (внешний ключ к родительской таблице)

... и поместите значение NULL в поле ForwardPrice или ForecastPoolPricedending в ожидании родительской сущности, поддерживаемой конкретной строкой. Затраты на пустое пространство в каждой строке практически не существовали бы, и успешность сжатия была бы очень высокой в ​​таблице, но для индексации и чтения ваша производительность была бы впечатляющей.

...