您可以有一个product表和一个单独的productadditioninfo表,其中包含3列:product id、additional info name和additional info value。如果颜色被许多但不是所有类型的产品使用,您可以在产品表中将其设置为可为空的列,或者将其放在productadditionalinfo中。 这种方法不是关系数据库的传统技术,但我看到它在实践中被大量使用。它可以灵活,性能良好。 steveyegge称之为properties模式,并写了一篇关于使用它的长文章。
4条答案
按热度按时间nnt7mjpx1#
如果我使用
Class Table Inheritance
含义:一个产品表,存储所有产品类型的公共属性。然后每个产品类型一个表,存储特定于该产品类型的属性-比尔·卡尔文
我最喜欢比尔·卡尔文的建议。。我可以预见一个缺点,我将试图解释如何避免成为一个问题。
当一个属性只对1类通用,然后变成对2类通用,然后变成3类通用时,我应该有什么应急计划?
例如:(这只是一个例子,不是我真正的问题)
如果我们卖家具,我们可能卖椅子、灯、沙发、电视等。电视可能是我们携带的唯一耗电的类型。所以我会把
power_consumption
属性tv_type_table
. 但后来我们开始使用家庭影院系统,它也有power_consumption
财产。好的,它只是一个其他产品,所以我将把这个字段添加到stereo_type_table
因为在这一点上这可能是最简单的。但随着时间的推移,当我们开始携带越来越多的电子产品时,我们意识到power_consumption
足够宽,应该在main_product_table
. 我现在该怎么办?将字段添加到
main_product_table
. 编写一个脚本来循环遍历电子设备,并从每个电子设备中输入正确的值type_table
到main_product_table
. 然后从每个type_table
.如果我总是用同样的方法
GetProductData
类与数据库交互,拉取产品信息;然后,如果代码中的任何更改现在需要重构,那么它们应该只属于该类。ajsxfq5m2#
您可以有一个product表和一个单独的productadditioninfo表,其中包含3列:product id、additional info name和additional info value。如果颜色被许多但不是所有类型的产品使用,您可以在产品表中将其设置为可为空的列,或者将其放在productadditionalinfo中。
这种方法不是关系数据库的传统技术,但我看到它在实践中被大量使用。它可以灵活,性能良好。
steveyegge称之为properties模式,并写了一篇关于使用它的长文章。
4xy9mtcn3#
@石心
我会一直带着eav和mvc来这里。
@比尔·卡文
以下是eav的一些缺点:
无法使列成为必需的(相当于notnull)。
无法使用sql数据类型验证条目。
无法确保属性名称的拼写一致。
无法将外键放在任何给定属性的值上,例如查找表。
你在这里提到的所有事情:
数据验证
属性名称拼写验证
必填列/字段
处理依赖属性的销毁
在我看来,它们根本不属于数据库,因为没有一个数据库能够像应用程序的编程语言那样在适当的级别上处理这些交互和需求。
在我看来,用这种方式使用数据库就像用石头敲钉子。你可以用一块石头来做,但是你不应该用一个更精确的,专门为这种活动设计的锤子吗?
在传统的表格布局中获取结果既复杂又昂贵,因为要从多行获取属性,需要对每个属性执行join。
这个问题可以通过对部分数据进行少量查询并用应用程序将它们处理成表格布局来解决。即使您有600gb的产品数据,如果您需要此表中每一行的数据,也可以成批处理它。
进一步说,如果您想提高查询的性能,您可以选择某些操作,例如报告或全局文本搜索,并为它们准备索引表,这些索引表将存储所需的数据并定期重新生成,比如说每30分钟一次。
你甚至不必担心额外数据存储的成本,因为它越来越便宜。
如果您仍然关心应用程序所执行操作的性能,那么您可以始终使用erlang、c++、go语言来预处理数据,然后在主应用程序中进一步处理优化后的数据。
ar5n3qh54#
对于所描述的类型层次结构的建模,至少有以下五个选项:
单表继承:一个表用于所有产品类型,具有足够的列来存储所有类型的所有属性。这意味着有很多列,其中大多数在任何给定的行上都是空的。
类表继承:一个表用于产品,存储所有产品类型的公共属性。然后每个产品类型一个表,存储特定于该产品类型的属性。
具体表继承:没有用于公共产品属性的表。相反,每个产品类型有一个表,存储公共产品属性和产品特定属性。
序列化lob:一个产品表,存储所有产品类型的公共属性。一个额外的列以xml、yaml、json或其他格式存储一个半结构化数据blob。这个blob允许您存储特定于每个产品类型的属性。您可以使用花哨的设计模式来描述这一点,例如正面和纪念品。但是不管怎样,你有一堆属性,在sql中很难查询到;您必须将整个blob取回应用程序并在那里进行排序。
实体属性值:一个表用于产品,另一个表将属性透视到行而不是列。eav在关系范式方面不是一个有效的设计,但是很多人还是使用它。这就是另一个答案中提到的“属性模式”。请参阅stackoverflow上eav标记的其他问题,以了解一些陷阱。
我在一个演示文稿《可扩展数据建模》中写了更多关于这方面的内容。
关于eav的其他想法:虽然很多人似乎喜欢eav,但我不喜欢。这似乎是最灵活的解决方案,因此是最好的。但是,请记住这句格言tanstaafl。以下是eav的一些缺点:
无法强制列(相当于
NOT NULL
).无法使用sql数据类型验证条目。
无法确保属性名称的拼写一致。
无法将外键放在任何给定属性的值上,例如查找表。
在传统的表格布局中获取结果既复杂又昂贵,因为要从多行获取属性,需要执行以下操作
JOIN
对于每个属性。eav给您带来的灵活性需要在其他方面做出牺牲,这可能会使您的代码变得比以更传统的方式解决原始问题更复杂(或更糟糕)。
在大多数情况下,没有必要有那么大的灵活性。在op关于产品类型的问题中,为特定于产品的属性创建每个产品类型的表要简单得多,因此至少对相同产品类型的条目强制执行一些一致的结构。
只有当每一行都必须被允许有一组不同的属性时,我才会使用eav。当您拥有一组有限的产品类型时,eav就太过致命了。类表继承将是我的首选。
更新2019:我越看到人们使用json作为解决“许多自定义属性”问题的解决方案,我就越不喜欢这个解决方案。这使得查询过于复杂,即使使用特殊的json函数来支持它们。存储json文档比存储在普通的行和列中需要更多的存储空间。
基本上,在关系数据库中,这些解决方案都不是简单有效的。拥有“可变属性”的整个想法从根本上与关系理论相悖。
归根结底,你必须选择一个对你的应用最不坏的解决方案。因此,在选择数据库设计之前,您需要知道如何查询数据。无法选择一个“最佳”的解决方案,因为任何解决方案都可能最适合给定的应用程序。