数据库中的冗余是否可以接受,或者它总是表明设计糟糕?

时间:2012-12-21 23:30:03

标签: database

我有两张桌子:

  • auth包含身份验证信息
  • users包含用户个人资料信息

auth有一个username列。这既可以作为登录凭据,也可以作为用户个人资料网址的一部分(例如example.com/profiles/username)。

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

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

3 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:1)

如果没有更广泛的应用图片,很难给出好的答案。我个人认为复制用户名等信息并不是一个好主意。

当你做出这样的设计决定时,你应该考虑系统维护/未来的发展等几点:

  • 将来用户是否会更改用户名?对于重复列,简单更新有时会成为更新多表的极具挑战性的任务(如果您复制一次信息,其他团队可以遵循该示例并一次又一次地执行此操作)。
  • 如果您的系统是由不同的团队开发或维护的(不一定非常了解您的系统),如果某些表格导致数据不一致,他们可能会错过重复项。

希望这会有所帮助。

答案 2 :(得分:1)

“少一次加入总是好的”。我对此提出异议。数据库旨在将表连接在一起。额外的连接通常需要工作,例如:

  1. 在第二个表的索引中找到包含该键的页面。非常快,因为索引应该在内存中。
  2. 在第二个表中检索值。
  3. 处理页面上的数据。
  4. 虽然这听起来像是很多工作,但实际上最多只需要几毫秒的努力。

    如果第二个表适合内存 - 或者在索引中包含用户名字段,那么第二个读取不是必需的 - 那么这一切都发生得非常快。不可否认,如果您尝试从平庸的硬件中获得每秒5,000笔交易,那么您可能会关心。在大多数情况下,额外的几毫秒(最多!)并不昂贵。

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

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

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