1

为什么有人会通过执行以下操作将实体(例如user)分配到多个表中:

user(user_id, username)
user_tel(user_id, tel_no)
user_addr(user_id, addr)
user_details(user_id, details)

你从这个数据库设计中得到什么加速奖励吗?这是非常违反直觉的,因为看起来执行链连接来检索数据听起来比使用选择投影要糟糕得多。

当然,如果只使用 user_id 和 username 来执行其他查询,那是一种加速,但值得吗?那么,真正的优势在哪里,以及适合这种数据库设计策略的兼容工作场景是什么?

后期编辑:在这篇文章的细节中,请假设一个完整的、唯一的实体,其属性在数量上没有变化(例如,汽车只有一种颜色,而不是两种,用户只有一个用户名/社交 sec 编号/入学编号/home address/email/etc.. 也就是说,我们处理的不是一对多关系,而是一对一、完全一致的实体描述。在上面的示例中,就是这种情况其中单个表已被“拆分”为与其拥有的非主键列一样多的表。

4

2 回答 2

1

通过以这种方式拆分用户,您在每个用户的用户中恰好有 1 行,它链接到 user_tel、user_details、user_addr 中的每行 0-n 行

这反过来意味着这些可以被认为是可选的,和/或每个用户可能有多个链接到他们的电话号码。总而言之,这是一个比硬编码更具适应性的解决方案,因此用户始终拥有最多 1 个地址、最多 1 个电话号码。

另一种方法是使用 ieuser.telephone1 user.telephone2等,但是这种方法违反 3NF(http://en.wikipedia.org/wiki/Third_normal_form) - 本质上,您引入了很多列来存储相同的信息

编辑

根据 OP 的附加编辑,假设每个用户将精确地拥有每个电话、地址、详细信息的 0 或 1,并且不再有,那么将这些信息存储在单独的表中是矫枉过正的。将列 user_id、username、tel_no、addr、details 存储在单个用户表中会更明智。

如果没记错的话,这在 3NF 内完全没问题。您说这不是关于正常形式的,但是如果每条数据都被认为与该特定用户直接相关,那么将它放在表中就可以了。

如果您稍后将表扩展为具有电话 1、电话 2(例如),那么这将违反 1NF。如果您有重复的字段(即多个用户共享一个地址,这是完全合理的),那么这违反了 2NF 反过来又违反了 3NF

关于违反 2NF 的这一点很可能是有人这样做的原因。

于 2012-04-17T08:43:24.000 回答
1

这个设计的作者可能认为在这样的“稀疏”结构中存储 NULL 可以比在单个表中“内联”更有效。这个想法可能是存储行,例如(1 , "john", NULL, NULL, NULL)在表(1 , "john")user,而在其他表中根本没有行。为此,NULL 的数量必须大大超过非 NULL(并且必须以正确的方式“混合”),否则这种设计很快就会变得更加昂贵。

此外,如果您不断选择单列,这可能会有所帮助。通过将列拆分为单独的表,您可以从存储角度使它们“更窄”,并在这种特定情况下降低 I/O (但不是一般情况下)。

在我看来,这种设计的问题远远超过了这些好处。

于 2012-04-17T10:38:57.350 回答