1

我有两张桌子:

  • auth包含认证信息
  • users包含用户个人资料信息

auth有一个username专栏。这既可用作登录凭据,又可用作用户配置文件 URL 的一部分(例如example.com/profiles/username)。

检索用户列表时,需要他们的用户名来创建他们个人资料的 URL。目前,我查询users表并加入auth表以获取此信息。username但是,如果也是 中的列,则可以避免该连接users,从而在两个不同的表中创建两个相同的列。

我不喜欢重复列的想法,但少一个连接总是好的。这是否表明数据库模式(或其他内容)需要重新设计,或者这是可以接受冗余的示例?

4

3 回答 3

7

规范化您的模式(即消除冗余)并非旨在解决时间效率问题,而是a)空间效率(通过消除数据的重复副本)和b)一致性(通过不在多个地方存储相同的信息,您不会冒着让他们不同意的风险)。从这个角度来看,必须使用联接是这些其他好处的代价。

于 2012-12-21T23:35:28.287 回答
1

如果没有对您的应用程序进行更广泛的了解,很难给您一个好的答案。我个人认为复制用户名等信息并不是一个好主意。

当您做出此类设计决策时,您应该考虑系统维护/未来发展等。几点:

  • 用户名将来会被用户更改吗?对于重复的列,简单的更新有时会变得非常具有挑战性来更新多个表(如果您复制一次信息,其他团队可以效仿该示例并一次又一次地进行)。
  • 如果您的系统是由不同的团队开发或维护的(他们不一定对您的系统有足够的了解),他们可能会错过一些表的重复并导致数据不一致。

希望这会有所帮助。

于 2012-12-21T23:52:23.853 回答
1

“少一个连接总是好的”。我对此有异议。数据库设计用于将表连接在一起。额外的连接通常需要以下工作:

  1. 在第二个表的索引中找到包含键的页面。非常快,因为索引应该在内存中。
  2. 在第二个表中检索该值。
  3. 处理页面上的数据。

虽然这听起来像是很多工作,但实际上最多只有几毫秒的努力。

如果第二个表适合内存——或者您在索引中包含用户名字段,因此不需要第二次读取——那么这一切都发生得很快。诚然,如果您试图从平庸的硬件中获得每秒 5,000 个事务,那么您可能会关心。对于大多数目的,额外的几毫秒(最多!)并不昂贵。

这些额外的工作能给你带来什么?它确保用户名是最新的用户名(如果已更改)。

您可能对您的应用程序有其他要求。性能可能很关键,在这种情况下,非规范化数据可能很有用(尽管复合索引可能在性能方面非常接近)。您可能处于内存有限的环境中,在这种情况下,在单个页面读取中加载所有用户数据可能很重要。用户名可能永远不会改变,在这种情况下,您可能会考虑将用户名作为表上的主键。也就是说,在某些情况下,非规范化将是一个严肃的选择。

肯定还有其他情况。例如,几乎所有的分析都来自非规范化的数据结构。

于 2012-12-22T00:31:37.057 回答