很抱歉提出这样的初学者问题,但是在数据库中使用一对一关系是否有真正的必要?您可以在一个表格内实现所有必要的字段。即使数据变得非常大,您也可以在SELECT
语句中枚举所需的列名,而不是使用SELECT *
。那么什么情况下需要进行这种分离呢?
很抱歉提出这样的初学者问题,但是在数据库中使用一对一关系是否有真正的必要?您可以在一个表格内实现所有必要的字段。即使数据变得非常大,您也可以在SELECT
语句中枚举所需的列名,而不是使用SELECT *
。那么什么情况下需要进行这种分离呢?
"超类和子类之间的1到0..1"是实现继承中"所有类分别存储在不同表格"策略的一部分。
"1到0..1"可以使用单个表格表示,其中"0..1"部分由可为空的字段覆盖。然而,如果关系大多是"1到0",只有少数"1到1"行,将"0..1"部分拆分成一个单独的表格可能会节省一些存储空间(和缓存性能)优势。一些数据库比其他数据库更加节俭地存储NULL值,因此这种策略变得可行的"截止点"可以差异很大。
真正的“一对一”垂直分区数据,这可能会影响缓存。数据库通常在页面级别实现缓存,而不是在单个字段的级别上,因此即使您只从行中选择了几个字段,通常也会缓存该行所属的整个页面。如果一行非常宽,而所选的字段相对较窄,则最终将缓存许多您实际上不需要的信息。在这种情况下,垂直分区数据可能很有用,因此仅缓存更窄、更频繁使用的部分或行,这样更多的行可以适合缓存,使缓存有效地变得“更大”。
垂直分区的另一个用途是改变锁定行为:数据库通常无法锁定单个字段,只能锁定整行。通过拆分行,您允许锁定仅发生在其一半上。
触发器通常也是特定于表的。虽然理论上您可以只有一个表,并使触发器忽略“错误的一半”行,但某些数据库可能会对触发器的操作加以限制,这可能使这种做法不切实际。例如,Oracle 不允许您修改变异表——通过拥有单独的表,只有其中一个可能是变异的,因此您仍然可以从触发器修改另一个表。
单独的表可能允许更精细的安全性。
在大多数情况下,这些考虑因素都不相关,因此您应该将“1对1”表合并为单个表。
另请参见:为什么在数据库设计中使用1对1关系?
我的个人看法。
我在一个工作场所工作,我们都在一个大型应用程序中进行开发,一切都是模块化的。例如,我们有一个users
表,我们有一个模块为用户添加Facebook详细信息,另一个模块为用户添加Twitter详细信息。我们可以决定卸载其中一个模块,并从我们的应用程序中删除所有相关功能。在这种情况下,每个模块都会向全局users
表添加自己的表,具有1:1的关系,如下所示:
create table users ( id int primary key, ...);
create table users_fbdata ( id int primary key, ..., constraint users foreign key ...)
create table users_twdata ( id int primary key, ..., constraint users foreign key ...)
如果在一个表格中放置两个一对一的表格,可能会出现语义问题。例如,如果每个设备都有一个遥控器,将设备和遥控器及它们的属性放在同一个表格中并不是很好。你甚至需要花时间去确定某个属性属于设备还是遥控器。
在某些情况下,您的一半列可能会长期为空,或者永远不会被填充。例如,汽车可以有一个配有大量特征的拖车,也可能没有。这样就会有许多未使用的属性。
如果您的表格有20个属性,只有其中4个偶尔使用,那么为了性能问题,将表格分成2个表格是有意义的。
在这种情况下,把所有东西都放在一个表里不是很好。此外,处理有45列的表格也并不容易!
如果将来需要将这些单独的数据与其他实体相关联,这可能会带来优势。
首先,我认为这是一个建模和定义什么构成独立实体的问题。假设您有一个只有一个单一地址的客户
。当然,您可以在单个表customer
中实现所有内容,但如果将来允许他拥有2个或更多地址,则需要重构该表(不是问题,但需做出明智决策)。
我还可以想到一个其他答案中没有提到的有趣情况,在这种情况下,拆分表可能会很有用:
再次想象,您有每个带有单个地址
的客户
,但此时拥有地址是可选的。当然,您可以将其实现为一堆可为NULL
的列,例如ZIP,state,street
。但是假设考虑到您确实拥有一个地址
,则state
是必需的,但ZIP
是可选的。如何在单个表中进行建模?您可以在customer
表上使用约束条件,但将其分割到另一个表中并使外键可以为NULL更容易。这样,您的模型更加明确地表明了实体address
是可选的,并且ZIP
是该实体的可选属性。
不太常见。
如果您需要实现一些安全性措施,例如让某些用户只能看到某些列(table1),而不能看到其他列(table2),那么可能会有所帮助。
当然,一些数据库(如Oracle)允许您在同一张表中进行此类安全性控制,但其他一些数据库则不行。
在实践中,我通常遇到两种常见的1:1关系:
IS-A关系,也称为超类型/子类型关系。这是指一种实体实际上是另一种实体的类型(EntityA IS A EntityB)。例如:
在所有这些情况下,超类型实体(例如人员、物品或汽车)将具有所有子类型共有的属性,而子类型实体将具有每个子类型各自独特的属性。子类型的主键与超类型的主键相同。
“老板”关系。这是指一个人是组织单位(部门、公司等)的唯一老板或经理或主管。当组织单位只允许一个老板时,表示老板的人员实体和表示组织单位的实体之间存在1:1关系。