我最近在思考规范化问题,但我发现我无法想象出数据库中应该存在1:1关系的情况。
姓名:社会安全号码(SSN)
? 我会将它们放在同一个表中。人员ID:地址ID
? 同样,放在同一个表中。
我可以举出无数个1:多或多:多(带有适当的中间表)的例子,但从未碰到过1:1的情况。
我是否漏掉了一些明显的东西?
我最近在思考规范化问题,但我发现我无法想象出数据库中应该存在1:1关系的情况。
姓名:社会安全号码(SSN)
? 我会将它们放在同一个表中。人员ID:地址ID
? 同样,放在同一个表中。我可以举出无数个1:多或多:多(带有适当的中间表)的例子,但从未碰到过1:1的情况。
我是否漏掉了一些明显的东西?
一个1:1的关系通常表示您已将更大的实体进行了某种分割。通常情况下,这是由于在物理模式中的性能原因,但如果同时期望有大量数据是“未知”的情况下,逻辑方面也可能发生这种情况(在这种情况下,您具有1:0或1:1,但不再支持更多)。
作为逻辑分区的示例:您拥有有关员工的数据,但是如果且仅当他们选择获得健康保险时,需要收集更大的数据集。我会将与健康保险相关的人口统计数据保存在另一个表中,以便更容易进行安全分区,并避免在与保险无关的查询中传输该数据。
物理分区的一个例子是相同的数据托管在多个服务器上。我可能会将有关健康保险人口统计数据保存在另一个州(例如HR办公室所在地),主数据库只能通过链接服务器连接到它...避免将敏感数据复制到其他位置,但使其可用于(在此假设罕见的)需要它的查询。
每当您需要一致的子集的查询更大的实体时,物理分区可以非常有用。
一个原因是数据库效率。1:1关系允许你拆分在行/表锁期间会受到影响的字段。如果表A有大量更新,而表B有大量读取(或来自另一个应用程序的大量更新),那么表A的锁定不会影响表B的操作。
其他人提出了一个很好的观点。根据应用程序等使用系统的方式,安全性也可以是一个很好的理由。我倾向于采取不同的方法,但这是一种限制对某些数据访问的简单方法。在紧急情况下,仅需拒绝对某个表的访问即可。
稀疏性。数据关系可能是技术上的1:1,但不必为每一行存在相应的行。因此,如果你有2000万行数据,并且有一些值仅出现在其中的0.5%中,则将这些列推送到可以稀疏填充的表中,可以节省大量空间。
一些稀缺资源的分配,例如一名员工一次只能被分配一辆公司车(例如每个卡车司机一辆卡车,每个出租车司机一辆出租车等)。最近我的同事给我举了这个例子。
婚姻关系(至少在禁止多夫多妻的法律管辖区):一个人同时只能与另一个人结婚。我从一本教科书中得到这个例子,它将其作为公司记录员工婚姻关系时一对一单一关系的例子。
匹配预订:当唯一的预订被分成两个实体后进行实现。例如,汽车租赁系统可能会将预订记录在一个实体中,然后在另一个实体中记录实际租赁情况。虽然这种情况也可以设计为一个实体,但是将实体分开可能是有意义的,因为并非所有预订都会被实现,也不是所有租赁都需要预订,而且这两种情况都非常普遍。
我再次重申,如果没有记录历史信息,大多数这些关系都是一对一的关系。因此,如果员工在组织中改变角色,或经理负责不同的部门,或者员工重新分配车辆,或者有人丧偶再婚,那么关系的参与者就会发生变化。如果数据库不存储任何有关这些一对一关系的先前历史记录,则它们仍然是合法的一对一关系。但是,如果数据库记录历史信息(例如为每个关系添加开始和结束日期),则它们基本上都会变成M:M关系。
历史注释有两个明显的例外:首先,某些关系很少更改,因此通常不会存储历史信息。例如,大多数 IS-A 关系(例如产品类型)是不可变的;也就是说,它们永远不会改变。因此,历史记录点无关紧要;这些将始终实现为自然的1:1关系。其次,预订-租赁关系分别存储日期,因为预订和租赁是独立的事件,每个事件都有自己的日期。由于实体具有自己的日期,而不是1:1关系本身具有开始日期,因此即使存储历史信息,这些关系也将保持为1:1关系。
我能想到的最普遍的情况是当你有二进制大对象(BLOB)时。假设您需要在数据库中存储大型图像(通常不是最佳存储方式,但有时限制会使它更加方便)。您通常会希望将blob放在单独的表中以提高非blob数据的查找效率。
从纯科学的角度来看,它们是无用的。
在实际的数据库中,有时将很少使用的字段保存在单独的表中是有用的:可以加快仅使用该字段的查询速度;避免锁定等问题。
有时候,为了限制对字段的访问,不使用视图而是将受限字段保留在单独的表中,并且只允许特定的用户访问这些表。