【问题标题】:Database schema-related problem数据库模式相关问题
【发布时间】:2010-11-26 09:04:29
【问题描述】:

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

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

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

一个包含 ID、Product_ID、属性和值的属性表。

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

【问题讨论】:

  • 如果您完全不知道可能的属性集是什么样的,那么您的动态方案确实有效。这是有问题的,因为您需要保持可能的属性一致(因此您最终不会为同一事物获得多个属性,例如“memory_size”,“gigabytes”,“bytes”,...)替代方案,如果您确实知道拥有一系列专用表的属性可能是什么,例如StorageProducts、ProcessingProducts 等拥有适用于各种产品类别的属性。
  • @John Pickup:你为什么不把那个好答案放到..an answer中?我会投赞成票,这是对 PerformanceDBA 答案的一个很好的补充。

标签: database-design relational


【解决方案1】:

这实际上是在向第六范式迈进,只是像你这样没有学术或经验背景的人不知道 (a) 它的名称和 (b) 规则和注意事项。这些人已经实现了通常所说的实体-属性-值或 EAV。如果做得好,那就没问题,并且有成千上万的医疗系统在这些表格中携带诊断和剂量信息。如果不是,那么使用和维护它就是一只狗的早餐。

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

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

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

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

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

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

  7. 不要通过视图更新。将所有更新保持在事务性的存储过程中,并将每一列(即适用于每个特定 ProductTypeProductsub-Product 表)插入或更新在一起。

    李>
  8. 巨大?商业数据库(不是免费软件)在处理大表或连接时没有问题。这实际上是一种非常有效的结构,并且允许非常快速的搜索,因为表实际上是面向列的(而不是面向行的)。如果人口是巨大的,那么它是巨大的,你自己算术。

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

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

要明确:

  • 第六范式是行由主键和最多一个属性组成。

  • 这是 6NF(至少对于 Product 表集群),然后通过 DataType 再次规范化(不是正常形式意义上的),以减少表的数量(否则每个属性只有一个表)。

  • 这会保留完整的 Rdb 控制(FK、约束等);而常见的 EAV 类型则不受 DRI 和控制的影响。

  • 这也有目录的雏形。

Link to Product Cluster Data Model

Link to IDEF1X Notation 适用于不熟悉关系建模标准的人。

更新

您可能对此▶5NF 6NF Discussion◀ 感兴趣。有时间我会写出来的。

【讨论】:

  • 我被您详尽的回答惊呆了。非常感谢!我注意到我作为 Web 开发人员的知识存在巨大差距。作为一名 IT 学生,我想了解更多关于这个主题的信息。你知道有什么好的文学作品可以让我深入研究吗?
  • @Bram。谢谢,不客气。大学毕业后我有很好的导师,这是最快的方法。 Rdb 设计与应用程序设计不同。跟随有实际经验的人。购买最好的教科书。网络上充斥着错误信息和肤浅信息,许多响应者阅读并从中发布。确保你做出区分。保持开放的心态,但不要开放到充满垃圾的程度。严格遵守标准,它们是由比我们更伟大的思想创造的。如果您转到我的链接中的目录,您可以查看其他答案。问好问题。
  • @Bram。为了比较和进一步理解,请查看此question/answer 以获得不同的 6NF 演绎版。
【解决方案2】:

最初我建议您使用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))

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

【讨论】:

    猜你喜欢
    • 2014-10-11
    • 1970-01-01
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 2011-10-26
    • 2018-11-21
    • 1970-01-01
    • 2019-08-27
    相关资源
    最近更新 更多