我在决定使用哪种方法时遇到了一些麻烦。
我有几个实体"类型",让他们称他们为A,B和C,他们共享一定数量的属性(约10-15)。我创建了一个名为ENTITIES的表,以及每个公共属性的列。
A,B,C也有一些(大部分)唯一属性(所有布尔值,可以是10到30左右)。 我不确定在建模表时遵循的最佳方法是什么:
我倾向于使用3,但我想知道是否有更好的解决方案。
答案 0 :(得分:9)
从数据库设计的角度来看,最干净的风格可能是继承,就像@yieldsfalsehood在他的评论中所建议的那样。这是一个包含更多信息,代码和链接的示例:
Select (retrieve) all records from multiple schemas using Postgres
但Postgres中当前的继承实现有许多限制。其中,您无法为所有继承表定义公共外键约束。仔细阅读the last chapter about caveats。
hstore
,json
(第9.2+页)/ jsonb(第9.4 +)页不同或更改属性集的批次的一个很好的替代方法,特别是因为您甚至可以在列中的属性上使用函数索引:
jsonb
indexing in Postgres 9.4 EAV类型的存储有其自身的优点和缺点。 This question on dba.SE提供了非常好的概述。
这是一种简单,蛮力的选择。从你的描述来看,你最终会得到大约100列,其中大多数是布尔值,大多数时候大多数都是NULL
。添加列entity_id
以标记类型。每种类型实施约束对于许多列来说有点尴尬。我不会为太多可能不需要的限制而烦恼。
The maximum number of columns allowed is 1600。由于大多数列为NULL,因此适用此上限。只要你把它保持在100到200列,我就不用担心了。 Postgres中的NULL存储非常便宜(basically 1 bit per column, but it's more complex than that.)。这只是每行10-20个字节。与人们可能认为(!)相反,磁盘上的小得多与hstore
解决方案相反。
虽然这样的桌子看起来对人眼来说是怪异的,但Postgres处理它并不是问题。 RDBMSes专注于暴力。您可以在基表的顶部定义一组视图(对于每种类型的实体),只包含感兴趣的列,并使用适用的列。这就像继承的逆向方法。但是这样你就可以拥有通用索引和外键等等。 我可能会这样做。
所有这一切,决定仍然是你的。这一切都取决于您的要求的细节。
答案 1 :(得分:0)
在我的工作中,我们的需求在迅速变化,并且很少因适当的架构升级而停机。在完成大记录时都包含大量的空值和高度归一化的(名称,值)后,我一直认为将所有常见属性都放在适当的列中,而将不同/不太常见的属性包含在“ hstore”存储桶。