【问题标题】:Database Modelling - Conceptually different entities with near identical fields数据库建模 - 具有几乎相同字段的概念上不同的实体
【发布时间】:2011-01-29 07:27:41
【问题描述】:

假设您有两组概念实体:

  • MarketPriceDataSet 有多个 ForwardPriceEntries
  • PoolPriceForecastDataSet 有多个 PoolPriceForecastEntry

两个不同的子对象具有几乎相同的字段:

ForwardPriceEntry 有

  • 开始日期
  • 结束日期
  • SimulationItemId
  • 远期价格
  • MarketPriceDataSetId(父表的外键)

PoolPriceForecastEntry 有

  • 开始日期
  • 结束日期
  • SimulationItemId
  • 预测池价格
  • PoolPriceForecastDataSetId(父表的外键)

如果我将它们建模为单独的表,唯一的区别就是外键和价格字段的名称。

关于两个几乎相同的表是否应该合并为一个的问题一直存在争议。

我想到的建模选项是:

  • 只需将它们保留为两个独立的单独表格
  • 将两个集合放在一个表中,并带有一个额外的“类型”字段,以及一个与任一父表的外键相等的 parent_id。这会牺牲参照完整性检查。
  • 将这两个集合放在一个带有附加“类型”字段的表中,并创建一个复杂的连接表序列以保持参照完整性。

你认为我应该怎么做,为什么?


其他可能相关或不相关的信息:

  • 两组数据关系松散:每组一组会被加载到内存中进行批处理,偶尔会从复制生成一组PoolPriceForecastEntries ForwardPriceEntries.

  • MarketPriceDataSetPoolPriceForecastDataSet 确实有不同的字段。可以将它们合并到一个表中,但是在一半的条目中会有无意义的字段。

【问题讨论】:

  • DataSet 对象怎么样?它们有什么不同吗?

标签: database-design relational-database


【解决方案1】:

“关于是否应该将两个几乎相同的表合并为一个的问题一直存在争议。”

有吗?

在数据库设计中,如果谓词不同,表应该保持独立。也就是说,如果表中各行所附加的含义不同。列集是否几乎或什至完全相等,无关紧要。

【讨论】:

    【解决方案2】:

    在您描述的情况下,被建模的主题通常符合一种称为“泛化专业化”的模式。两个先前的答案讨论子类型的事实支持了这一点。对象模型倾向于通过使用子类型和继承来处理 gen-spec。

    关系模型也可以处理 gen-spec,但它稍微复杂一些,并且通常不会在数据库入门中教授。你要做的是有几个表,每个子类型一个,保存子类型特有的键和非键属性。与超类型相关并由所有子类型继承的数据通常合并到一个表中。

    您可以使用这些表的键来玩一个技巧,以减少存储和处理。在子类型表中,使用返回超类型条目的外键作为子类型表的主键。它保证存在,并且保证是唯一的。何必再发明一把钥匙呢?

    如果您搜索“泛化专业化关系建模”,您将获得关于该主题的十几篇文章。其中一些非常好。也可以关注标签:

    【讨论】:

      【解决方案3】:

      由于实体共享如此多的属性,您可以将它们视为子类型。

      从逻辑上讲,您将拥有 PriceEntry 的超类型以及 ForwardPriceEntry 和 PoolPriceForecastEntry 的子类型。要回答的一个问题是价格对于超类型是否通用。我会假设它是。

      现在的问题是如何物理实现子类型。您可以采取 3 种方法:

      1. 为每个子类型创建一个表(Rolldown)
      2. 创建包含所有属性的单个表(汇总)
      3. 为每个子类型(身份)创建一个超类型表和一个子类型表

      这些方法中的每一种都有利有弊。有关每种方法的优缺点的讨论,请参阅Getting Physical with Subtypes

      在这种情况下,由于子类型共享许多属性,您可以采用汇总方法并创建一个表。

      PriceEntry 表可能如下所示:

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

      您仍然可以对 MarketPrice 和 PoolForecast 列强制执行 FK。您还可以添加表级检查约束以确保至少填充一个 FK。


      但是,由于 2 个子类型之间只有一个属性不同,因此许多优点和缺点并没有强烈地指向一个方向。所以,最后,我可能会选择让数据模型易于理解和使用。对我来说,两张表(rolldown)方法取得了很好的平衡;从概念上讲,它比汇总更容易理解,并且在开发时它比标识更容易使用(没有连接或多次插入/更新)。

      【讨论】:

        【解决方案4】:

        如果您打算以大致相同的方式使用来自两个子类型的数据,我建议将所有数据放入包含所有五个字段的单个表中...

        • 开始日期
        • 结束日期
        • SimulationItemId
        • 远期价格
        • MarketPriceDataSetId(父表的外键)

        ... 并在 ForwardPrice 或 ForecastPoolPricedepending 字段中放置一个空值,以等待特定行支持的父实体。每行空值的空间成本几乎不存在,压缩成功率在表上会非常高,但对于索引和读取,您的性能会令人印象深刻。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多