当广泛引用关系数据库中的多值属性时,它是多么好?
让我举个例子来说明我的意思。假设我有下表:
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
在数据库中处理此类情况的任何更快的方法?或者是否有现代数据库的内置功能可以利用?
答案 0 :(得分:6)
在字段中包含多个值仅在数据在数据库中为自重时才有用,即如果您只读取数据库中的字段并在之后处理它。
只要您想在查询中使用字段中的值,就必须解析值以进行比较,从而获得巨大的性能损失。如果您将值放在单独的记录中,如第二个示例所示,以便您可以在其上添加索引,那么查询的速度将快10 000倍并不现实。
表中有一百万条记录不是问题。我们有一些表中有超过1亿条记录。
答案 1 :(得分:3)
除了其他人关于规范化所说的内容之外,我想回答一下你的问题中的“或现代数据库的任何内置功能?”:
PostgreSQL有一个非常漂亮的扩展名为hstore
,它完全按照高度优化的方式完成。
hstore
数据类型本质上是一个键/值对,您可以在其中存储任何内容。在你的例子中是这样的:
INSERT INTO user_attributes
(user_id, , attributes)
VALUES
(1, ('att1 => x, att2 => y'));
将密钥att1
和att2
插入列属性中。可以将其编入索引以快速查找。
您可以使用以下语法查询数据:
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