在SQL Server中存储(产品)属性的最佳模式

database database-design entity-framework sql sql-server

我们正在开始一个新项目,我们需要在数据库中存储产品和许多产品属性。技术堆栈是MS SQL 2008和Entity Framework 4.0 / LINQ,用于数据访问。

产品(和产品表)非常简单(SKU,制造商,价格等)。但是,每种产品也存在许多属性(想想工业小部件)。这些可能从颜色到认证到管道尺寸。每个产品可能具有不同的属性,有些可能具有相同属性的倍数(例如:认证)。

目前的建议是我们基本上会有一个名称/值对表,其中FK返回到每行中的产品ID。

属性表的示例可能如下所示:

ProdID     AttributeName     AttributeValue
123        Color             Blue
123        FittingSize       1.25
123        Certification     AS1111
123        Certification     EE2212
123        Certification     FM.3
456        Pipe              11
678        Color             Red
999        Certification     AE1111
...

注意:属性名称可能来自查找表或枚举。

所以这里的主要问题是:这是做这样的事情的最佳模式吗?表现如何?查询将基于产品和属性表的JOIN,并且通常需要许多WHERE来过滤特定属性 - 最常见的搜索将是基于一组已知/期望的属性来查找产品。

如果有人对此类数据有任何建议或更好的模式,请告诉我。

谢谢! -ed

一般承认的答案

您即将重新发明可怕的EAV模型,Entity-Attribute-Value。这是出于现实生活中的问题而臭名昭着,出于各种原因,戴夫的回答涵盖了许多问题。

幸运的是,SQL客户咨询团队(SQLCAT)有一个关于该主题的白皮书,即性能和可伸缩性的语义数据建模的最佳实践 。我强烈推荐这篇论文。不幸的是,它没有提供灵丹妙药,一个千篇一律的解决方案,因为问题没有解决方案。相反,您将学习如何在固定的可查询架构和灵活的EAV结构之间找到平衡,这种平衡适用于您的特定情况:

语义数据模型可能非常复杂,并且在语义数据库通常可用之前,挑战仍然是在每个应用程序的纯对象模型和纯关系模型之间找到最佳平衡。成功的关键是理解问题,对这些问题进行必要的缓解,然后进行测试,测试和测试。如果您要找到最佳设计,可伸缩性测试是一个关键的成功因素。


热门答案

由于以下几个原因,这将成为问题:

  • 您的实体查询将更难写。当需要进行演示时,将这些查询的结果转换为类似于ViewModel的内容将会很痛苦,因为它将涉及每个产品的支点。

  • 在阅读某些类型的数据时,了解您的数据类型将是艰难的。你打算把它存储为字符串吗?例如,DateTimes保存的数据多于默认的.ToString()实现写入字符串。如果您尝试存储浮点值,也会遇到问题。

  • 您的对象的数据完整性存在风险。在这个“存储数据”中放置属性应该只是主要产品表的属性是一种诱惑。也许设计从一开始就是半合理的,但我向你保证,经过一段时间后,人们才会开始将物品扔进包里。因此,使用如此松散定义的结构来保持对象的完整性将非常困难。

  • 您的索引很可能不是最理想的。再想想应该在您的产品表上的属性。现在,您将不得不在一个列上进行索引,而是强制在“类型”表上创建一个可能非常大的复合索引。

  • 由于您显然计划丢弃正确的数据类型并使用字符串,因此数值数据范围查询的性能可能会很差。

  • 您的表将变大,减慢备份和查询。而不是一个4字节的整数,你将不得不存储更多的任何大小的整数。

最好使用“IS-A”关系以更“传统”的方式规范化表格。例如,您可能有Pipes,它是一种Product,但有更多属性。您可能有Stoves,它是一种产品,但仍然有更多属性。

如果您确实拥有通用数据库以及不受数据完整性规则约束的各种其他属性,那么您可能需要考虑将数据存储在XML列中。除非我对您的业务了解更多,否则很难告诉您正确的设计选择。

IMO这是一个设计反模式。这个想法的警笛歌曲吸引了许多开发人员进入一个无法维护的应用程序的岩石。



许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因