我不是在询问有关索引还是分区的问题,我在询问一个选择,在添加大号之间。列或将数据添加为行而不是。 说明:我们目前有一个请求,要求设计来处理某些特定产品的多个属性及其值 产品可能达到1亿条记录,每个产品可能有多个属性,因此ProductProperties的表可能达到数十亿。 有些人想到在ProductProperties表,Property1和value1,Property2和value2等中添加属性作为列.... 如果产品不包含属性的值,则此属性的相关字段将为null。此外,他们还将添加大约80-100个属性,以便能够动态地覆盖各种属性。 建筑师拒绝这种方法,因为这不是一个好的设计。 任何人都可以告诉我如何达到良好的设计和良好的性能。 感谢
答案 0 :(得分:5)
这个问题出现了许多伪装。在您的情况下,您似乎拥有一系列产品,每个产品可能具有不同的属性集。我认为您需要一种以可扩展的方式存储这些属性的方法,以便您可以向系统添加新产品。
方法1:行上的通用字段+补充元数据
通过将产品属性元数据规范化为自己的表格,可以稍微修改您建议的第一种方法:
使用一些通用字段构建产品表(Code1,Code2,IntVal1,IntVal2,FloatVal1 ......)
构建一组辅助父子参考表ProductType
和ProductAttribute
(或其他一些参考表),其中包含产品表中哪些列包含哪些属性的指南。
构建功能,将其解释为应用程序的数据访问层。
这样做的主要优点是结构有效查询。缺点是product
表的内容在没有补充元数据的情况下是不透明的。然而,其他方法的低效率和复杂性通常大大超过了这个缺点。
如果不同产品类型的数量相对较小,您还可以使用元数据生成解释元数据的产品表上的视图或一系列视图。这减轻了不透明度的许多问题。
另一个优点是产品上具有多个筛选条件的查询不必针对非常大的子表执行多个连接。如果表上的各个字段可以为空,则每个字段的开销相对较小(通常每列一个字节,具体取决于平台)。未使用的字段会在记录上浪费大量空间。
方法2:实体属性值
这通常被认为是解决这类问题的方法。在这种情况下,您在父子关系中有Product
和ProductAttribute
个表,其中一些参考数据会根据产品类型过滤产品属性类型。
这种方法在概念上看起来很优雅并且是可扩展的,但是查询并且占用相当多的磁盘空间是非常低效的。某些数据库设计黑客可以在各种平台上使用,以缓解性能问题。您尚未指定您正在使用的DBMS平台,因此很难为您指明正确的方向。 EAV结构的主要优点和缺点是:
无需更改数据库schena(+)
查询效率低且繁琐,特别是如果您想按多个属性过滤( - )
更多磁盘空间使用量。 ( - )
除非您有令人信服的要求,否则不推荐使用EAV结构。
方法3:XML字段
用Fredrick Lundh的话来说:'now you have two problems'。 XML字段是无限可扩展的 - 您可以将任何您想要的内容放入其中,但它们对您的应用程序以外的任何内容都是不透明的,并且它们查询速度慢而且繁琐。从SQL查询中的XML字段中获取数据要比存储在列上的数据要多得多。
通常,在数据库中使用XML字段来存储非本质上是XML文档的东西是个坏主意。许多人写过关于在数据库中滥用XML字段的不明智之处。我建立ETL过程以从XML字段中提取数据的个人经验使我同意。除非你有令人信服的理由,否则最好避免使用。
<强>结论强>
方法1类似于您最初提出的方法,但将列元数据移动到其自己的结构中。尽管它看起来并不优雅,但几乎在所有情况下它都是最佳方式。
答案 1 :(得分:0)
我会创建两个表:Product
和ProductProperties
。
Product
将包含单个产品的基本属性。 name
,weight
,selling_quantity
等项目之间需要和通用的内容。
ProductProperties
将包含其他所有内容。规范化属性的属性,命名它们并创建表。你需要的只是一个Product
的FK,你已经准备好了。 1:如果大多数属性都是空的,那么表之间的关系要远远好于拥有80个或更多属性的单个表(我怀疑每个产品需要80-100个属性,但我不知道你列出的是什么类型的产品)
我没有使用数十亿行的第一手经验,但数据库应该规范化,而不是用空列填充。这个答案似乎支持了我的想法:Optimal database structure - 'wider' table with empty fields or greater number of tables?
我认为当ProductProperties
表的行数超过unsigned bigint
时,会出现第一个问题。可能需要一段时间,我希望......
答案 2 :(得分:0)
现有答案是正确且非常好的。这是一个新的想法:显然,将设计分成两个表(Products,ProductAttributeValues)是最常规化和正确的方法。
但性能可以超越架构纯度。唯一重要的设计目标是将整个解决方案的成本降至最低。没有别的了。如果非规范化模式足以提高性能,您可以在其他地方节省性能,或者降低硬件成本,那么这是正确的做法。 只有TCO很重要。那很简单。
非规范化,如果它保存你的工作,即使是长期工作,或者它是否可以节省硬件。