每个类似物体一张桌子?

时间:2009-08-04 08:42:56

标签: database database-design data-structures normalization

我为绘画店写了一个应用程序。我的系统中有这些课程:商店,购物车,货架和面包店。

他们有这个属性:

购物:X,Y,名称,宽度,高度,类型,地址

购物车位置:X,Y,名称,宽度,长度,类型,容量

rack:X,Y,名称,宽度,长度,类型,高度,balance_limit

面包店:X,Y,名称,宽度,长度,类型,open_hours

现在我想在我的数据库中表示这些类。但是你可以看到上面的所有类都有类似的东西:

X,Y,宽度,高度,名称和类型。让他们与众不同的是:

购物:地址

购物车所在地:容量

rack:balance_limit

面包店:open_hours

我知道将来所有这些类型的对象都会拥有自己的新属性,并且他们将获得所有这些属性同时拥有的新属性。

而且我知道上面没有提到的新类型的物品将具有与商店,购物车场所,货架和面包店相同的一些属性。

我想创建允许我添加新属性和新对象的数据库结构。并添加将在同一时间添加到每个类的新属性。而且我希望系统设计清晰,并允许我对它进行简单的数据库查询。

所以我的问题是:

我应该为每种类型的对象(商店,购物车的地方,货架,面包店)制作数据库表,因为它会更清楚,还是应该将它们组合成一个表,因为它们具有相似的属性列表?

我希望你能让我知道为什么一个解决方案会比另一个解决方案更好。我希望在这里得到一些实用的建议,不仅“你应该这样做,因为它只是正确的方式,公理”。

6 个答案:

答案 0 :(得分:1)

这不是一个简单的问题...... SQL数据库不擅长建模类层次结构。

你需要一个好的ORM。

我把一个类层次结构放在一个表中,这样做:

首先,我确保它是相关的:例如,在同一个表中为网络CMS放置节点,文章等是有道理的,因为这些都是同一事物的变体。

您的想法是需要创建用于搜索,索引和进行SQL查询的数据库列,但不需要将所有信息存储在数据库列中。您可以将其余部分存储在BLOB列中的序列化对象中。

在表中,有 - 当然是一个列,指示该行是哪个类的实例 - 一些所有类共有的“核心”列,基本上是基类字段。 - 其他列仅由某些子类使用,但我需要进行搜索,因此需要对其进行索引 - 包含来自对象的所有其他数据的BLOB。

基本上,当我在数据库中存储一个对象时,将填充根据其类的相关列,并将其余数据(甚至整个对象)推送到BLOB中。

关于这一点的好处是,如果添加一个不需要搜索或索引的成员值,只存储,则不需要将其放在数据库列中,因此不需要对其进行更改数据库根本就是:它将存储在序列化的BLOB中。唯一要做的是在反序列化代码中为此成员添加一个默认值,因此该类中已经存在于数据库中且没有此成员的对象将具有相当的默认值。

如果您愿意,也可以对对象格式进行版本控制,它会变得更复杂。

然而,这种方案有一些缺点:

限制难以适用: - 您只能将约束应用于具有列的字段。 - 由于某些列只出现在某些类中,因此数据库需要了解一下类层次结构。

例如,您可能希望将地址放在单独的表中,并添加相关字段(邮政编码,国家/地区,街道,数字等):将所有这些放在主表中会添加太多列。此外,您还会在某个时候添加一些客户或其他不同表中的内容并且还有一个地址,因此最好将地址放在单独的表中并参考它们。

对于人或公司等也是如此。

现在一家商店有一个地址,但推车没有,我猜,所以你必须在数据库DDL中表示你的表中的一行必须参考一个地址,如果它是“shop”类型而不是类型“车”。

它可能有点毛茸茸。

另外,如果您有10个商店和100,000个购物车,例如,为了提高性能,分割表格可能会很有趣,因此您可以获得一个漂亮的小型快餐桌和一个大桌子。


现在还有其他解决方案:

例如,您可以将所有代码和基本成员放在基类中,但是使tableName成为派生类中更改的类属性。这样,只需更改表名,所有代码都适用于不同的表,但您不必重写任何表。

然后每节课获得1张桌子。

如果您的类层次结构变得更复杂,您当然可以在每个表上应用上述方法。


如何在两者之间做出选择?

基本上,如果您创建一个Web CMS并存储在一个表中,那么从Node派生的类的对象如下: - 文章 - 带图例的图片 - 画廊 - 等等

所有这些对象基本上是相同的东西。 它们都有Title,TextContent字段,属于ParentNode等等

如果在TextContent中搜索关键字“foo”,则如果所有对象都在同一个表中,则会更容易。

如果要列出ParentNode的所有子节点以在网页上显示它们,如果所有内容都在1个表中,则也会更容易。

所以在这种情况下,第一种方法确实是一种好处。

现在,在您的情况下,对象不是那么相似。

我个人甚至不会给他们相同的基类。 我会创建一个Mixin名称“ThingWithCoordinates”(可能更短)并将其添加到类中。

现在,也许面包店离商店很近,它可以从它继承,但推车和货架,可能不是。

在你的情况下,我肯定会使用几个表。在每个表中,如果你需要存储几个类,我会使用第一种方法。

最重要的是,您的类层次结构(以及表格)必须基于相关的东西(汽车经销商和面包店是商店),而不是实际上没有任何共同点的对象之间碰巧存在的常见特征(如购物车和店)。为此,有一些mixin来共享公共代码,但不是基类。

答案 1 :(得分:1)

我建议:

  1. 正确设计domain model,而不考虑数据库问题。共享属性的实体(例如 name )并不意味着它们以任何方式相关。虽然他们很可能......
  2. 将此设计映射到数据库结构,选择众所周知的Object-Relational Structural Patterns(参见Database Design)。
  3. 使用适当的ORM解决方案开发您的产品(最好是允许您之后修改基础数据库结构的解决方案)。
  4. 如果遇到性能问题,请考虑使用(de)normalizing数据库来解决问题。

答案 2 :(得分:0)

是的,您应该为每个对象使用一个表,因为它们是它们自己的实体。 如果将这些表映射到对象,则无需连接多个表,从而提高效率。

然后,每个对象在开发和复杂性方面都是孤立的。

答案 3 :(得分:0)

您从“共享”常用项目表中获得了哪些好处?

如果没有,那么就不要这样做 - 只需将它们放在不同的表格中(特别是如果它们将来会进一步分化)。

我猜你没有使用ORM?

答案 4 :(得分:0)

在“泛化专业化关系建模”上搜索网页。

当出现这种模式时,您会找到几篇关于如何设计SQL数据库的好文章。最好的文章遵循您提供指导的标准,而不是规定规范规则。

答案 5 :(得分:0)

如果共性与shop_size类似,那么我建议为此创建一个单独的表。

原因是通过标准化可以获得其他信息,因此,例如,它可以很容易地显示宽度和长度的下拉列表,因为可能有许多商店具有相同的测量值。

您还可以查看此表中的数据以获取其他信息。

主要是,你获得灵活性,IMO。