具有多列的单个固定表与灵活的抽象表

时间:2010-10-25 04:42:53

标签: sql mysql database database-design data-modeling

我想知道你是否有一个网站上有十几种不同类型的商品(商店,餐馆,俱乐部,酒店,活动)需要不同的字段,是否有利于创建一个包含如此定义的列的表
示例商店:

shop_id | name | X | Y | city | district | area | metro | station | address | phone | email | website | opening_hours

或者更类似于此的抽象方法:

object_id | name        
---------------
1         | Messy Joe's  
2         | Bate's Motel 

type_id | name
---------------
1       | hotel
2       | restaurant


object_id | type_id
---------------
1         | 2
2         | 1

field_id | name           | field_type
---------------
1        | address        | text
2        | opening_hours  | date 
3        | speciality     | text

type_id | field_id
---------------
1       | 1
1       | 2
2       | 1
2       | 3

object_id | field_id | value
1         | 1        | 1st street....
1         | 3        | English Cuisine

当然,如果预定义值,它可能会更抽象(例如:专业可以有自己的列表)

如果我采用抽象方法,它可以非常灵活,但是对于大量连接,查询会更复杂。 但我不知道这是否会影响性能,执行这些“更复杂”的查询。

我很想知道这两种方法的优缺点是什么。我可以想象一下自己,但我没有经验证实这一点。

5 个答案:

答案 0 :(得分:77)

答案 1 :(得分:9)

在您的问题中,您至少同时提出了两个主要问题。这两个问题是E-A-V和gen-spec。

首先,我们来谈谈E-A-V。你的最后一个表(object_id,field_id,value)本质上是一个E-A-V。 E-A-V有一个好处,而E-A-V则有下行空间。好处是结构非常通用,几乎可以容纳描述几乎所有主题的任何数据体。这意味着您可以继续进行设计和实施,无需进行数据分析,也无需了解主题,也不必担心错误的假设。缺点是在检索时,您必须在构建数据库之前进行数据分析,以便提出任何意义上的查询。这比检索效率要严重得多。但是你也会在检索效率方面遇到可怕的问题。只有两种方法可以了解这个陷阱:通过它来实践它或从那些拥有它的人那里了解它。我推荐阅读。

其次,你有一个gen-spec案例。您的表(object_id,type_id)捕获gen-spec(泛化特化)模式以及相关表。如果我不得不在酒店和餐馆之间进行概括,我可以称之为“公共住宿”或“场地”。但是我不确定我是否了解你的情况,而且你可能正在驾驶一些比这两个名字更普遍的东西。毕竟,你已经在你的列表中包含了“事件”,并且事件不是我脑海中的一种场所。

在其他回复中,我引用了其他人的关于gen-spec和关系模型的读物  When two tables are very similar, when should they be combined?

但是我不愿意向你发送同一个方向,因为我不清楚你想在构建数据库之前想出一个数据的关系模型。一组数据的关系模型和相同数据的E-A-V模型几乎完全相互矛盾。在你甚至探索如何在关系数据模型中表达gen-spec之前,你似乎必须做出这个选择。

答案 2 :(得分:3)

当你开始需要大量不同的实体时(甚至在......之前),nosql解决方案将比任何一种选择都简单得多。 只需存储每个实体/记录以及您需要的确切字段。

{
   "id": 1,
   "type":"Restaurant",
   "name":"Messy Joe",
   "address":"1 Main St.",
   "tags":["asian","fusion","casual"]
}

答案 3 :(得分:2)

“抽象”方法更好地称为“标准化”,看起来像第三范式(3NF)。

另一个称为“非规范化”,并且可以是一个有效的性能选项......当您使用规范化方法遇到速度问题时,而不是之前。

答案 4 :(得分:1)

如何在代码中显示列表?我猜Listing为超类型,ShopRestuarant等作为子类型?

假设这是一个如何将子类型映射到关系数据库的情况。通常有三种选择:

  • 选项1:每个子类型的单个表格, 重复的共同属性 每个表(名称,ID等)。
  • 选项2:所有对象的单表(单表方法)
  • 选项3:超类型的表格和每个子类型的表格

没有普遍正确的解决方案。我的偏好通常是从选项3开始;它提供了一个可以使用的原型结构,很好地规范化并且可以很容易地扩展。它意味着用于检索每个实例的单个连接 - 但是RDBMS针对连接进行了很好的优化,因此在实践中它不会真正导致性能问题。

选项2对于查询(无连接)可能更高性能,但如果其他表需要引用所有超类型实例(外键扩散),则会导致问题。

选项1乍一看似乎是最高效的,尽管有2个警告:(1)改变不具备弹性。如果添加新的子类型(以及不同的属性),则需要更改表结构并进行迁移。 (2)它可能效率低于看起来的效率。由于表填充稀疏,因此某些DB不能特别有效地存储它。因此,它可能比选项1效率低 - 因为查询引擎可以比搜索膨胀的稀疏表空间更快地进行连接。

选择哪个真正归结为了解问题的详细信息。我建议您阅读一些选项:this article是一个很好的起点。

HTH