与数据库架构相关的问题

时间:2010-11-26 09:04:29

标签: database-design relational

我有一个关于数据库的理论问题。为了使它更具体,我想到了一个例子。

假设我有一个包含产品的商店。我有很多不同的产品。并非每种产品都具有相同的适用性。例如,我可以用千兆字节定义硬盘的大小,但不能在CPU上使用相同的属性,因为它不适用。我想要的是一个数据库,我可以动态地向产品添加属性。我能想出的唯一一件事就是:

一个带有ID,名称和描述的产品表。

一个具有ID,Product_ID,Property和Value的属性表。

通过这种方式,我可能会得到一个巨大的,我认为不那么高效的属性表。这已经困扰了我很长一段时间了。有谁知道我的问题更好的解决方案?

2 个答案:

答案 0 :(得分:10)

这实际上正朝着第六范式转变,只是像你这样没有学术或经验背景的人不知道(a)名称和(b)规则和警告。这些人已经实现了通常所知的实体 - 属性 - 值或EAV。如果做得好,一切都很好,并且有数千个医疗系统在那里携带诊断和剂量信息。如果不是,则使用和维护一只狗的早餐。

  1. 首先确保您拥有真实且完整的5NF Product

  2. 始终使用完整的声明参照完整性; CHECK个约束和RULES

  3. 永远不要将所有内容放入一个带有VARCHAR()值的表中。始终使用正确(适用)的数据类型。这意味着您将拥有多个表,每个DataType一个,并且不会失去控制或完整性。

  4. 同样,任何关联表(其中对另一个表[例如供应商]有多个引用)必须是分开的。

    • 我提供的数据模型具有完整的控制权;它包括一个简单的目录,可用于验证和导航。您需要添加每个CHECK约束和RULE,以确保数据和参照完整性不会丢失。这意味着,例如:
      • 用于CPUSpeed列,该列存储在ProductDecimalCHECK,表示其处于适当的值范围
      • 表示Product组合的数据类型正确的每个子CHECKProductType-ColumnNo
    • 这种结构比大多数EAV好,而且不完全是6NF 。
  5. 保留Product中的所有必填列;仅将sub-Product表用于可选列。

  6. 对于每个这样的(例如Product)表,您需要创建一个View(虚线),它将构建EAV / 6NF表中的5NF行。您可能有多个观看次数:Product_CPUProduct_Disk

  7. 请勿通过视图进行更新。在存储过程中保持所有更新的事务性,并插入或更新每个列(即适用于每个特定Product的{​​{1}}和sub-Product表)。

  8. 巨大的?商业数据库(不是免费软件)对大型表或联接没有问题。这实际上是一个非常有效的结构,并允许非常快速的搜索,因为这些表实际上是面向列的(不是面向行的)。如果人口巨大,那么它是巨大的,做你自己的算术。

  9. 您还需要一个表,ProductType(或属性)的查找表。这是目录的一部分,基于Property

  10. 更好的解决方案是获得完整,正式的第六范式。如果只有一个或几个表需要可选列,则不需要。

    要明确:

    • 第六范式该行包含主键,最多包含一个属性。

    • 这是6NF(至少对于Product表集群),然后再按DataType再次标准化(不是在Normal Form意义上),以减少表的数量(否则每个属性将有一个表)。

    • 这保留了完整的Rdb控制(FK,约束等);而常见的EAV类型并不需要DRI和控制。

    • 这也有目录的基础。

    <强> Link to Product Cluster Data Model

    那些不熟悉关系建模标准的人

    Link to IDEF1X Notation

    更新

    您可能对此▶5NF 6NF Discussion◀感兴趣。我会在某个时候写出来。

答案 1 :(得分:0)

最初我建议你有一个productproperty表来模拟产品和属性之间的关系。这将允许您将许多产品与特定属性相关联。

但是,我并不热衷于将每个属性存储的值作为1:1存储。如果您有一个propertyvalue表将属性与值相关联,那可能是最好的。然后,你放弃了productproperty表,而选择了一个更丰富的productpropertyvalue表,它可以完整地描述产品,它的属性和它们的价值之间的关系。

或许你可以拥有以下内容:

product => (ID (unique key), Name, Description)
property => (ID (unique key), Description)
propertyvalue => (ID (unique key), propertyID (foreign key), value)
productpropertyvalue => (ID (unique key), productID (foreign key), propertyValueID (foreign key))

当然,属性值可能很复杂而不是简单的字符串或整数,但希望这会带你走向正确的方向。