关系数据库中的多值属性?

时间:2011-09-22 05:37:11

标签: sql database database-design relational-database

当广泛引用关系数据库中的多值属性时,它是多么好?

让我举个例子来说明我的意思。假设我有下表:

UserID          Attribute1

User1           a,b,c
User2           x,y,z
User3           a,x,y
User4           c,b,z
[a,b,c,x,y,z are to be strings]

还有另一位用户User5,根据他的Attribute1是否与其他4位用户中的任何一位用户匹配,我必须向其提出一些建议。

[在图表数据库中,任务本来可以轻松得多,因为我可以使用相同的关系从相应的用户创建多个节点。]

现在,这个表只是对实际数据库外观的微观抽象。如果不是数百万,表中的行数可能会达到数十万。此外,多个值实际上可能远远超过3.除此之外,数据库可能负载很重,在这种情况下,可能会出现一些问题。

那么,在这种情况下,多值属性是否有用?或者有更好的方法做同样的事情吗?我能想到的一个显而易见的方法是将其存储为:

UserID          Attribute1

User1           a
User1           b
User1           c
User2           x
User2           y
User2           z
User3           a
User3           x
User3           y
User4           c
User4           b
User4           z

在数据库中处理此类情况的任何更快的方法?或者是否有现代数据库的内置功能可以利用?

3 个答案:

答案 0 :(得分:6)

在字段中包含多个值仅在数据在数据库中为自重时才有用,即如果您只读取数据库中的字段并在之后处理它。

只要您想在查询中使用字段中的值,就必须解析值以进行比较,从而获得巨大的性能损失。如果您将值放在单独的记录中,如第二个示例所示,以便您可以在其上添加索引,那么查询的速度将快10 000倍并不现实。

表中有一百万条记录不是问题。我们有一些表中有超过1亿条记录。

答案 1 :(得分:3)

除了其他人关于规范化所说的内容之外,我想回答一下你的问题中的“或现代数据库的任何内置功能?”:

PostgreSQL有一个非常漂亮的扩展名为hstore,它完全按照高度优化的方式完成。

hstore数据类型本质上是一个键/值对,您可以在其中存储任何内容。在你的例子中是这样的:

INSERT INTO user_attributes
(user_id, , attributes)
VALUES
(1, ('att1 => x, att2 => y'));

将密钥att1att2插入列属性中。可以将其编入索引以快速查找。

您可以使用以下语法查询数据:

SELECT *
FROM user_attributes
WHERE attributes @> ('att1 => "Some Value"')

这将返回具有名为att1的键的所有行以及将其映射到值“Some Value”的所有行。上面的语句将使用列上的现有索引,因此查找几乎与“实际”列一样快。上面的语句在我的笔记本电脑上需要大约2毫秒才能在一个包含100.000行的表中找到一行。

您还可以查询已定义特定属性的行,而不管值是什么:

SELECT user_id,
       (attributes -> 'att1')
FROM user_attributes
WHERE attributes ? 'att1'

将找到定义att1的所有行,并输出这些行的值。

答案 2 :(得分:1)

对于nn表,您可以将其规范化为3个表(在事务模型中)users - user_attribute - user_attribute表由用户和属性的主键组成的属性。键通常被索引,因此非常快阅读ops

问题后编辑

Users
int Id PrimaryKey
string name

User_Attribute
UserId PrimaryKey (FK to Users.Id)
AttributeId PrimaryKey (FK to Attributes.Id)

Attributes
int Id PrimaryKey
Value

这会导致一个表只保存用户,一个表只保存属性,一个表保存用户持有什么

例如

   Users      User_Attribute      Attrubutes      
id  Name   UserId AttributeId  Id Value
1   User1  1      1            1  Att1
2   User2  1      2            2  Att2
           2      1            3  Att3  
           2      3