Onetomany与父数据库设计

时间:2013-02-01 18:33:51

标签: database entity-relationship one-to-many

下面是一个代表我的问题的数据库设计(这不是我的实际数据库设计)。对于每个城市,我需要知道哪些餐馆,酒吧和酒店是可用的。我认为这两个设计不言自明,但是:

首先设计:在城市和餐馆,酒吧和酒店之间建立一对多的关系。

第二种设计:只在城市和地方之间建立一对多的关系。

哪种设计是最佳做法?第二种设计关系较少,但是我可以获得一个城市的所有餐厅,酒吧和酒店以及自己的数据(property_x / y / z)吗?

更新:这个问题出了问题,也许是我的错,因为我不清楚。

  • 餐厅/酒吧/酒店类是“地方”的子类(两者都有 设计)。
  • 餐厅/酒吧/酒店类必须让父母“地点”
  • 餐厅/酒吧/酒店类有自己的特定数据(property_X / Y / X)

Database design

6 个答案:

答案 0 :(得分:3)

优先设计

您的数据以及SQL和ERD的可读性/可理解性是最重要的考虑因素。出于可读性的目的:

  • city_id放入place。原因:地点在城市。由于是酒店,酒店不是刚刚发生在的地方。

要考虑的其他设计要点是将来如何扩展此结构。让我们比较添加一个新的子类型:

  • 在设计一中,您需要添加一个新表格,与“地点”的关系以及与city的关系
  • 在设计二中,您只需添加一个新表和“place”的关系。

我再次使用第二种设计。

效果第二

现在,我猜,但是将city_id置于子类型中的原因可能是您预计在某些特定用例中它更有效或更快,这可能是忽略可读性的一个很好的理由/易懂。但是,在您部署的实际硬件上衡量性能之前,您不知道:

  • 哪种设计更快
  • 性能差异是否会降低整个系统的性能
  • 其他优化方法(调优SQL或数据库参数)实际上是否是处理它的更好方法。

我认为设计一是尝试在ERD上对数据库进行物理建模,这是一种不好的做法。

过早的优化是SW Engineering中许多邪恶的根源。

子类型方法

在ERD上实施子类型有两种解决方案:

  1. 公共属性表,每个子类型一个表(这是您的第二个模型)
  2. 包含子类型属性的附加列的单个表。
  3. 在单表方法中,您将拥有:

    • 子类型列TYPE INT NOT NULL。这指定该行是餐馆,酒吧还是酒店
    • property_X上的额外列property_Yproperty_Zplace

    这是一个利弊快速表:

    单表方法的缺点:

    • 扩展列(X,Y,Z)在单个表方法上不能为NOT NULL。您可以实现行级约束,但是会丢失简单的NOT NULL
    • 的简单性和可见性
    • 单个表非常宽且稀疏,尤其是在添加其他子类型时。你可以达到最高。某些数据库中的列数。这可能会使这种设计非常浪费。
    • 要查询特定子类型的列表,您必须使用WHERE TYPE = ?子句进行过滤,而table-per-subtype是一个更自然的`FROM HOTEL INNER JOIN PLACE ON HOTEL.PLACE_ID = PLACE。 ID“
    • 恕我直言,在面向对象语言中映射到类更难,更不明显。如果要通过Hibernate,Entity Beans或类似的
    • 映射此数据库,请考虑避免

    单表方法的优点:

    • 通过合并到单个表中,没有连接,因此查询和CRUD操作更有效(但这种小差异会导致问题吗?)
    • 不同类型的查询是参数化WHERE TYPE = ?),因此在代码中而不是在SQL本身(FROM PLACE INNER JOIN HOTEL ON PLACE.ID = HOTEL.PLACE_ID)中更易于控制。

    没有最好的设计,你必须根据你最常做的SQL和CRUD操作的类型,以及可能的性能来选择(但请参见上面的一般警告)。 / p>

    <强>建议

    在所有条件相同的情况下,我建议默认选项是您的第二个设计。但是,如果您有一个压倒一切的问题,例如我上面列出的那些,请选择其他实现。但不要过早优化。

答案 1 :(得分:0)

他们两个都没有。

如果我需要选择一个,我会保留第二个,因为之后需要创建的外键和索引的数量。
但是,更好的方法是:创建一个包含各种场所(酒吧,餐馆等)的表格,并为每一行分配一个具有该地点类型值的列(应用 COMPRESS 子句,列中预期的类型)。它将改善结构的性能和可读性,并且更容易维护。

希望这会有所帮助。 : - )

答案 2 :(得分:0)

您不会在任何子位置表中显示备用列。我认为你不应该将类型数据分成表名,如'bar','restaurant'等 - 这些应该是place表中的类型。

我认为你应该有一个地址表 - 其中一列是城市。然后每个地方都有一个地址,您可以在需要时轻松按城市分组。 (或州或邮政编码或国家等)

答案 3 :(得分:0)

我认为最好的选择是第二个。在第一种设计中,存在数据错误的可能性,因为一个地方可以被分配给一个城市中的特定餐馆(或任何其他类型)(例如A)并且同时可以被分配给不同城市中的另一个餐馆。 (例如B)。在第二种设计中,一个地方总是与特定的城市联系在一起。

答案 4 :(得分:0)

<强>首先
两种设计都可以为您提供所有适当的数据。

第二
如果所有扩展类都要实现该位置(这对于您的实现来说显而易见),那么将它作为父对象的一部分包含在内将是更好的做法。这将建议选项2.

啄:
事情是,即使你很难找到每个特定PLACE的类型,更容易知道一个类型(CHILD)总是一个地方(PARENT)。当您想象选项2的结果集时,您可以想到这一点。考虑到这一点,我建议采用第一种方法。

注意:
第一个没有更多的关系,它只是分裂它们。

答案 5 :(得分:0)

如果酒吧,餐厅和酒店拥有不同的属性集,那么它们是不同的实体,应该由3个不同的表来表示。但为什么你需要摆放桌子?我建议它抛弃它并为你的3个实体设置3个表,就是这样。

在代码中,将公共属性收集到父类中比在每个子类中重复它们更有条理和有效 - 当然。但正如上面的spathirana评论,数据库设计不像OOP。当然,通过将地点的常用属性粘贴到“地点”表中,您将节省重复的列名。但它也会增加复杂性: - 无论何时想要参考酒吧,餐厅或酒店,您都必须加入餐桌 - 每当您想要添加新的酒吧,餐厅或酒店时,您必须插入两张桌子 - 你必须在......等时更新两个表。

拥有3个没有位置表的表格也是最可靠的设计。但那不是我来自的地方。我正在考虑干净,简单的数据库设计,其中单个实体意味着单个表中的单个行。关系数据库中没有“is-a”关系。外键关系是“has-a”。好的,我确定有例外,但你的情况并不例外。