84669 人学习
152542 人学习
20005 人学习
5487 人学习
7821 人学习
359900 人学习
3350 人学习
180660 人学习
48569 人学习
18603 人学习
40936 人学习
1549 人学习
1183 人学习
32909 人学习
我在表格设计方面没有太多经验。我的目标是创建一个或多个满足以下要求的产品表:
支持多种产品(电视、手机、PC...)。每种产品都有不同的参数集,例如:
手机将具有颜色、尺寸、重量、操作系统...
PC 将拥有 CPU、HDD、RAM...
参数集必须是动态的。您可以添加或编辑您喜欢的任何参数。
如果没有针对每种产品的单独表格,如何满足这些要求?
@StoneHeart
我会一直使用 EAV 和 MVC 来到这里。
@比尔·卡文
您在这里提到的所有这些事情:
在我看来,根本不属于数据库,因为没有任何数据库能够像应用程序的编程语言那样在适当的级别上处理这些交互和需求。
在我看来,以这种方式使用数据库就像用石头锤钉子一样。您可以用石头来完成此操作,但您不应该使用更精确且专门为此类活动设计的锤子吗?
可以通过对部分数据进行少量查询并使用应用程序将其处理为表格布局来解决此问题。即使您有 600GB 的产品数据,如果您需要此表中每一行的数据,也可以批量处理它。
进一步如果您想提高查询的性能,您可以选择某些操作,例如报告或全局文本搜索并为其准备索引表,该索引表将存储所需的数据并定期重新生成,假设每 30 分钟重新生成一次。
您甚至不需要担心额外数据存储的成本,因为它每天都变得越来越便宜。
如果您仍然关心应用程序执行的操作的性能,您始终可以使用 Erlang、C++、Go 语言来预处理数据,然后在主应用程序中进一步处理优化后的数据。 p>
您至少有以下五个选项来对您描述的类型层次结构进行建模:
单表继承:一个表适用于所有产品类型,有足够的列存储所有类型的所有属性。这意味着很多列,其中大多数在任何给定行上都是 NULL。
类表继承:一张产品表,存储所有产品共有的属性类型。然后每种产品类型一个表,存储特定于该产品类型的属性。
具体表继承:没有通用产品属性的表。相反,每种产品类型一张表,存储常见产品属性和产品特定属性。
序列化 LOB:一个产品表,存储所有产品类型通用的属性。一个额外的列以 XML、YAML、JSON 或某种其他格式存储半结构化数据的 BLOB。此 BLOB 允许您存储特定于每种产品类型的属性。您可以使用奇特的设计模式来描述这一点,例如 Facade 和 Memento。但无论如何,您都无法在 SQL 中轻松查询大量属性;您必须将整个 blob 提取回应用程序并在那里进行排序。
Entity-Attribute-Value:一张产品表,以及一张将属性旋转到行而不是列的表。就关系范式而言,EAV 并不是一个有效的设计,但仍然有很多人使用它。这就是另一个答案提到的“属性模式”。请参阅 StackOverflow 上使用eav 标记的其他问题,了解一些陷阱。
我在演示文稿可扩展数据建模中写了更多相关内容。
关于 EAV 的其他想法:虽然很多人似乎喜欢 EAV,但我不喜欢。这似乎是最灵活的解决方案,因此也是最好的解决方案。但是,请记住这句格言TANSTAAFL。以下是 EAV 的一些缺点:
NOT NULL
JOIN
EAV 的灵活性程度需要您在其他方面做出牺牲,这可能会使您的代码比以更传统的方式解决原始问题复杂(或更糟)。
并且在大多数情况下,没有必要具有这种程度的灵活性。在OP关于产品类型的问题中,为每个产品类型创建一个用于产品特定属性的表要简单得多,因此至少对于相同产品类型的条目强制执行一些一致的结构。
仅当必须允许每一行可能具有一组不同的属性时,我才会使用 EAV。当您的产品类型有限时,EAV 就显得有些过分了。类表继承将是我的第一选择。
2019 年更新:我越多地看到人们使用 JSON 作为“许多自定义属性”问题的解决方案,我就越不喜欢该解决方案。即使使用特殊的JSON 函数,它也会使查询变得过于复杂> 支持他们。与存储在普通的行和列中相比,存储 JSON 文档需要更多的存储空间。
基本上,这些解决方案在关系数据库中都不是简单或有效的。拥有“可变属性”的整个想法从根本上与关系理论不一致。
归根结底,您必须选择一种对您的应用影响最小的解决方案。因此,在选择数据库设计之前,您需要知道如何查询数据。无法选择一种“最佳”解决方案,因为任何解决方案都可能最适合给定的应用程序。
@StoneHeart
我会一直使用 EAV 和 MVC 来到这里。
@比尔·卡文
您在这里提到的所有这些事情:
在我看来,根本不属于数据库,因为没有任何数据库能够像应用程序的编程语言那样在适当的级别上处理这些交互和需求。
在我看来,以这种方式使用数据库就像用石头锤钉子一样。您可以用石头来完成此操作,但您不应该使用更精确且专门为此类活动设计的锤子吗?
可以通过对部分数据进行少量查询并使用应用程序将其处理为表格布局来解决此问题。即使您有 600GB 的产品数据,如果您需要此表中每一行的数据,也可以批量处理它。
进一步如果您想提高查询的性能,您可以选择某些操作,例如报告或全局文本搜索并为其准备索引表,该索引表将存储所需的数据并定期重新生成,假设每 30 分钟重新生成一次。
您甚至不需要担心额外数据存储的成本,因为它每天都变得越来越便宜。
如果您仍然关心应用程序执行的操作的性能,您始终可以使用 Erlang、C++、Go 语言来预处理数据,然后在主应用程序中进一步处理优化后的数据。 p>
您至少有以下五个选项来对您描述的类型层次结构进行建模:
单表继承:一个表适用于所有产品类型,有足够的列存储所有类型的所有属性。这意味着很多列,其中大多数在任何给定行上都是 NULL。
类表继承:一张产品表,存储所有产品共有的属性类型。然后每种产品类型一个表,存储特定于该产品类型的属性。
具体表继承:没有通用产品属性的表。相反,每种产品类型一张表,存储常见产品属性和产品特定属性。
序列化 LOB:一个产品表,存储所有产品类型通用的属性。一个额外的列以 XML、YAML、JSON 或某种其他格式存储半结构化数据的 BLOB。此 BLOB 允许您存储特定于每种产品类型的属性。您可以使用奇特的设计模式来描述这一点,例如 Facade 和 Memento。但无论如何,您都无法在 SQL 中轻松查询大量属性;您必须将整个 blob 提取回应用程序并在那里进行排序。
Entity-Attribute-Value:一张产品表,以及一张将属性旋转到行而不是列的表。就关系范式而言,EAV 并不是一个有效的设计,但仍然有很多人使用它。这就是另一个答案提到的“属性模式”。请参阅 StackOverflow 上使用eav 标记的其他问题,了解一些陷阱。
我在演示文稿可扩展数据建模中写了更多相关内容。
关于 EAV 的其他想法:虽然很多人似乎喜欢 EAV,但我不喜欢。这似乎是最灵活的解决方案,因此也是最好的解决方案。但是,请记住这句格言TANSTAAFL。以下是 EAV 的一些缺点:
NOT NULL
)。JOIN
。EAV 的灵活性程度需要您在其他方面做出牺牲,这可能会使您的代码比以更传统的方式解决原始问题复杂(或更糟)。
并且在大多数情况下,没有必要具有这种程度的灵活性。在OP关于产品类型的问题中,为每个产品类型创建一个用于产品特定属性的表要简单得多,因此至少对于相同产品类型的条目强制执行一些一致的结构。
仅当必须允许每一行可能具有一组不同的属性时,我才会使用 EAV。当您的产品类型有限时,EAV 就显得有些过分了。类表继承将是我的第一选择。
2019 年更新:我越多地看到人们使用 JSON 作为“许多自定义属性”问题的解决方案,我就越不喜欢该解决方案。即使使用特殊的JSON 函数,它也会使查询变得过于复杂> 支持他们。与存储在普通的行和列中相比,存储 JSON 文档需要更多的存储空间。
基本上,这些解决方案在关系数据库中都不是简单或有效的。拥有“可变属性”的整个想法从根本上与关系理论不一致。
归根结底,您必须选择一种对您的应用影响最小的解决方案。因此,在选择数据库设计之前,您需要知道如何查询数据。无法选择一种“最佳”解决方案,因为任何解决方案都可能最适合给定的应用程序。