2

我不是在问索引或分区,我问的是一个选择,在添加大号之间。列或将数据添加为行。说明:我们目前有一个请求,要求设计一个处理多个属性的设计,某些特定产品的值可能达到 1 亿条记录,每个产品可能有多个属性,因此 ProductProperties 表可能达到数十亿。有些人想到在ProductProperties表中添加属性作为列,Property1和value1,Property2和value2等......如果产品不包含该属性的值,则该属性的相关字段将为空。他们还将添加大约 80-100 个属性,以便能够动态覆盖广泛的属性。建筑师拒绝了这种方法,因为这不是一个好的设计。谁能告诉我如何达到良好的设计和良好的性能。谢谢

4

3 回答 3

5

这个问题以多种形式出现。在您的情况下,您似乎拥有一系列产品,每个产品可能具有不同的属性集。我认为您需要一种以可扩展的方式存储这些属性的方法,以便您可以将新产品添加到系统中。

方法 1:行上的通用字段 + 补充元数据

您建议的第一种方法可以通过将产品属性元数据规范化到自己的表中来稍微修改:

  • 使用一些通用字段(Code1、Code2、IntVal1、IntVal2、FloatVal1 ...)构建您的产品表

  • 构建一组补充的父子引用表ProductTypeProductAttribute(或一些类似的),其中包含有关产品表中哪些列包含哪些属性的指南。

  • 构建功能以将其解释为应用程序的数据访问层。

这样做的主要优点是结构查询效率高。缺点是product表格的内容在没有补充元数据的情况下是不透明的。然而,其他方法的低效率和复杂性通常远远超过这一缺点。

如果不同产品类型的数量相对较少,您还可以使用元数据在产品表上生成一个视图或一系列视图,以解释元数据。这减轻了很多不透明的问题。

另一个优点是对产品具有多个过滤条件的查询不必针对非常大的子表执行多个连接。如果表上的各个字段可以为空,则每个字段的开销相对较小(通常每列一个字节,具体取决于平台)。未使用的字段将浪费记录上的大量空间。

方法二:实体-属性-值

这通常被提议作为此类问题的解决方案。在这种情况下,您拥有父子关系中的表和一些参考数据,这些参考数据根据产品类型筛选产品属性类型ProductProductAttribute

这种方法在概念上看起来很优雅并且是可扩展的,但查询起来很繁琐且效率低下,并且占用了相当多的磁盘空间。可以在各种平台上使用一些数据库设计技巧来缓解性能问题。您尚未指定您正在使用哪个 DBMS 平台,因此很难为您指明正确的方向。EAV结构的主要优点和缺点是:

  • 无限灵活,无需更改数据库架构 (+)

  • 查询效率低下且繁琐,特别是如果您想按多个属性进行过滤 (-)

  • 更多的磁盘空间使用。(-)

通常不推荐使用 EAV 结构,除非您有令人信服的要求。

方法 3:XML 字段

套用 Fredrick Lundh 的话说:“现在你有两个问题”。XML 字段是无限可扩展的——您可以将任何您想要的内容放入其中,但除了您的应用程序之外,它们对任何东西都是不透明的,而且查询起来既缓慢又繁琐。从 SQL 查询中的 XML 字段中获取数据比存储在列上的数据要多得多。

通常,在数据库中使用 XML 字段来存储本质上不是 XML 文档的东西是一个坏主意。许多人写过关于在数据库中滥用 XML 字段的不明智的做法。我构建 ETL 流程以从 XML 字段中提取数据的个人经验使我同意这一点。除非您有令人信服的理由,否则最好避免。

结论

方法 1 类似于您最初提出的方法,但将列元数据移到其自己的结构中。尽管它看起来并不优雅,但它几乎是所有情况下的最佳选择。

于 2012-04-15T16:56:33.473 回答
0

现有的答案是正确且非常好的。这是一个新的想法:显然,将设计拆分为两个表(Products、ProductAttributeValues)是最规范和正确的方法。

但是性能可以胜过架构的纯度。唯一重要的设计目标是将整个解决方案的成本降至最低。别的什么都不重要。如果非规范化模式提高了足够的性能,您可以在其他地方节省性能工作,或者降低硬件成本,那么这是正确的做法。只有 TCO 很重要。就这么简单。

非规范化,如果它甚至在长期内节省了您的工作,或者如果它节省了硬件。

于 2012-04-15T17:15:43.077 回答
0

我会创建两个表:ProductProductProperties.

Product将包含单个产品的基本属性。诸如 , 等项目之间需要和常见的name那种weight东西selling_quantity

ProductProperties将包含其他所有内容。规范化属性的属性,命名它们并创建你的表。您只需要一个 FKProduct就可以开始了。如果大多数属性为空,则表之间的 1:n 关系比拥有 80 个或更多属性的单个表要好得多(我怀疑每个产品都需要 80-100 个属性,但我不知道您列出的是哪种产品) .

我没有任何使用数十亿行的第一手经验,但是数据库应该被规范化,而不是用空列填充。这个答案似乎支持我的想法:Optimal database structure - 'wider' table with empty fields or more numbers?

我认为您的第一个问题出现在您的ProductProperties表的行数超出unsigned bigint处理能力时。这可能需要一段时间,我希望...

于 2012-04-15T16:48:37.903 回答