问题概述。
比方说,我有一个名为TableA的表,该表具有固定属性PropertyA,PropertyB和PropertyC。这已经足以满足您自己的网站需求,但随后突然有一些客户希望在您的网站上使用自定义字段。
ClientA想要添加PropertyD和PropertyE。 ClientB想要添加PropertyF和PropertyG。
要注意的是,这些客户互不相干。现在想像一下,如果您有更多的客户端,则仅在TableA中添加可为空的字段的解决方案将很麻烦,并且最终将导致一堆表格。或者至少我认为情况是可以纠正我的。如果我那样做会更好吗?
现在我想到了两种解决方案。我在问是否有更好的方法来做,因为我对权衡及其未来表现不那么自信。
data_id并非完全是外键,但它存储附加到表A行的任何相应客户端属性。使用client_id作为属性表和表A上唯一的外键。
这似乎是某种反模式,但我可以想象这种查询将很容易,但是它要求开发人员知道应该从中选择什么属性表。我不确定很多表是否是一件坏事。
我相信它会更优雅一些,并可以根据需要轻松添加更多字段。更不用说这些是我需要做其他所有事情的唯一表。只是想像。我将请求属性添加到属性表中,如下所示:
Properties
-------------
1 | PropertyD
2 | PropertyE
3 | PropertyF
4 | PropertyG
每当我保存任何数据时,我都会标记所有属性,只要它们可用。对于此示例,我要保存存储在ID为1的“客户”表中的ClientA。
Property_Mapping
--------------------------------------------------------
property_id | table_a_id | property_value | client_id
--------------------------------------------------------
1 | 1 | PROPERTY_D_VALUE | 1
2 | 1 | PROPERTY_E_VALUE | 1
我想这很可能会导致查询的复杂性,但这是一个权衡。我打算将client_id放在property_mapping上,以防万一客户端需要相同的字段。有什么建议吗?
答案 0 :(得分:1)
您已发现Entity-Attribute-Value反图案。对于关系数据库,这是一个可怕的想法。它使您的查询更加复杂,并且占用4-10倍的存储空间。
在Stack Overflow的一个旧答案中,我介绍了几种替代方法的优缺点:
在演示文稿中:
作为EAV造成麻烦的一个示例,请考虑如果您的一位客户说PropertyD必须是强制性的(即等效于NOT NULL
,而PropertyE必须是UNIQUE
,您将如何应对。同时,另一位客户说PropertyG应该限制为一组有限的值,因此您应该使用ENUM
数据类型,或者对允许值表使用外键。
但是您无法使用“属性”表实现任何这些约束,因为所有属性的所有值都存储在同一列中。
使用此反模式时,您将失去关系数据库的功能,例如数据类型和约束。