数据库设计问题

时间:2009-04-05 02:38:09

标签: database-design

我很欣赏有关我所担心的一些意见。

我的数据库中有一个[User]表,包含您期望的基本内容,如用户名,密码等...

此应用程序要求我为每个用户跟踪大量属性。这么多,我可能会用完列(行存储空间)。

我很想添加一个UserProperties表,其中包含UserID,PropertyKey和PropertyValue列。这种方法非常符合要求。

我担心的是,如果每个用户都说100个属性,当数据库中有100万个用户时,我们将拥有100,000,000个属性行。

我认为使用UserID上的聚簇索引,该访问仍然会快速尖叫,并且您实际上存储的数据量与使用mega-columns方法时的数据量相同。

有关性能问题的任何想法或想法?想要更好的数据库设计?

谢谢!

更新

首先,非常感谢所有伟大的回应!

我一直在四处寻找可能性,有一件事让我烦恼。我需要经常查询其中一些属性,更糟糕的是,这些查询可能涉及同时查找多达10个这些属性的标准的所有用户。

因此,我现在倾向于采用巨型列方法,但可能将数据拆分为一个(或多个)单独的表,形成一个一对一的关系,用于关键用户ID。

我正在使用LinqToSql,虽然我认为有这么多列的表格不够优雅,但我认为考虑所有的挑战和权衡,它可能是正确的,但我仍然渴望听到其他意见。 / p>

10 个答案:

答案 0 :(得分:11)

您所描述的是实体 - 属性 - 值数据库,它通常用于您描述的情况,稀疏数据绑定到单个实体。

E-A-V表易于搜索。问题不是找到行,而是找到相关的行。

为不同的实体提供不同的表提供了域建模,但它们也提供了弱形式的元数据。在E-A-V中没有这样的抽象。 (Java类似于E-A-V将声明所有函数的形式参数都是Object类型 - 所以你不会进行类型检查。)

我们可以轻松查找属性键,但没有对这些属性键进行分组。

维基百科有一篇关于E-A-V的非常好的文章,但现在读它 - 它主要是一位作者的作品,并且是为了“改进”。

答案 1 :(得分:7)

我建议您考虑称为垂直分区的方法。这意味着您继续使用UserID键定义表,您可以将它们称为User1,User2等。当您达到数据库的最大行大小时,启动一个新表。这种方法的好处是值仍然是真正的数据库属性。这将最终节省处理此数据的时间,例如:数据绑定。

要回答的关键问题是:这些属性真的是什么?它们是否代表您必须收集的有关用户的信息结构。如果是这样,建模它们的最佳方法是使它们成为列。您必须求助于垂直分区的唯一原因是数据库的行大小限制。

另一方面,如果要求灵活的属性系统,那么一定要使用属性键/属性值系统。例如,如果允许用户动态定义自己的属性,那么您肯定需要键/值系统。但是,如果您了解数据的结构并合法地为用户确定了数百个属性,我会说键/值不是最好的方法。

作为旁注,我必须说你应该质疑具有大量属性的实体。它们可能是有效的,但是你很可能在概念层面遗漏了一些实体。换句话说,mabe所有这些属性与用户本身无关,而与用户相关的其他实体无关。

答案 2 :(得分:3)

UserProperties表方法就是我对其进行建模的方法。如您所建议的,userID上的聚簇索引将意味着对userID的范围搜索将是快速的(即,对于与单个用户相关的所有属性)。可能还会在UserID和PropertyKey上添加非聚集索引,以便为每个用户选择单个键值2。

答案 3 :(得分:1)

我怀疑你在Users表中有这么多的1对1数据值,你将用完行空间。您应该只使用用户ID作为外键将1对多的值卸载到另一个表中。我发现你的用户表不太可能需要这么多VARCHAR()字段,这些字段无法以某种方式从主表值变成FK。您要维护哪种用户属性?

答案 4 :(得分:1)

以任何方式对属性进行逻辑分组?您可能并不总是需要访问每个属性。此外,如果它们在逻辑上分组,则更容易理解可用的属性,新属性适合的位置等等。

分组可以与用户有一对一或一对多的关系...

答案 5 :(得分:1)

我们已在多个项目中实施了UserProperties策略。这是一种常见的模式,使用适当的索引,我们从未遇到过性能问题。

另一个优点是,如果需要管理用户访问,您可以拥有两个或更多属性表。例如,一般属性可以在PublicUserProps表中,而敏感信息(我不知道你要存储什么,但ssn,工资单信息等)可能在ControlledUserProps表中,只有一些用户可以阅读或编辑权利。

答案 6 :(得分:1)

我喜欢Mitch Wheat和你自己描述的元表方法。但是,如果您有一些字段比其他字段更频繁地使用(例如名称等),那么您可能会发现在User表中使用这些字段可能是有益的,然后将用户表链接到UserProperties。我想这一切都取决于你的设计的确切细节。

答案 7 :(得分:1)

我能想到的一些选择:

  • 位字段:您可以在其中存储许多值,您可以根据需要添加更多字段,甚至可以使用单独的表格
  • 将最常用的设置放在用户表中,并将每个用户可能没有的设置放在第二个表中
  • 仅存储与默认设置不同的设置

答案 8 :(得分:1)

鉴于所述限制,我认为你真的没有其他选择!

好的,您可以在多个表中拆分用户属性,共享与其主键(和聚簇索引)相同的UserId,但这可能会也可能不会提高性能

如果你只谈论100个属性,这可以由一个表处理(在MS-SQL max中是1023个非键列);如果属性只是稀疏填充,那么用户属性表可能更节省空间(只有你的探查器肯定知道)

答案 9 :(得分:1)

  

我认为使用UserID上的聚簇索引,该访问仍然会快速尖叫,并且您实际上存储的数据量与使用mega-columns方法时的数据量相同。

我认为使用属性表,您最终会存储的内容远远超过您实际需要的内容。即用户标识的额外索引,属性键列,以及属性值需要能够处理通用性值的事实,这使得难以优化。

我的建议是尝试将所有内容放在一个表中,然后使用一些测试数据将其激活。 IF 它不起作用然后你可以沿着多表解决方案甚至非数据库解决方案的路径(毕竟它们不是银子弹)。