代码之家  ›  专栏  ›  技术社区  ›  Pulsehead

是否曾经有过使用数据库1:1关系有意义的时候?

  •  145
  • Pulsehead  · 技术社区  · 16 年前

    • Name:SSN ? 我会把它们放在同一张桌子上。
    • PersonID:AddressID ? 还是同一张桌子。

    我可以举出无数个1:many或many:many(带有适当的中间表)的例子,但从来没有1:1的例子。

    25 回复  |  直到 4 年前
        1
  •  175
  •   Godeke    16 年前

    1:1关系通常表示您出于某种原因对较大的实体进行了分区。通常这是因为物理模式中的性能原因,但如果预期大量数据同时“未知”(在这种情况下,您有一个1:0或1:1,但没有更多),那么这种情况也可能发生在逻辑端。

    作为逻辑分区的一个示例:您有关于员工的数据,但需要收集更大的数据集,如果且仅当他们选择拥有健康保险。我会将有关医疗保险的人口统计数据保存在不同的表中,这样既可以简化安全分区,又可以避免在与保险无关的查询中拖拽这些数据。

    物理分区的一个例子是在多台服务器上承载相同的数据。我可能会将医疗保险人口统计数据保存在另一个州(例如,人力资源办公室所在的州),主数据库可能仅通过链接服务器链接到该数据。。。避免将敏感数据复制到其他位置,同时使其可用于需要它的查询(这里假设很少)。

    物理分区可能很有用 无论何时 您的查询需要较大实体的一致子集。

        2
  •  131
  •   kemiller2002    10 年前

    一个原因是数据库效率。通过1:1关系,可以拆分在行/表锁定期间受影响的字段。如果表A有大量更新,而表b有大量读取(或有大量来自其他应用程序的更新),那么表A的锁定不会影响表b中的情况。

    其他人提出了一个很好的观点。安全性也是一个很好的理由,这取决于应用程序等如何影响系统。我倾向于采用不同的方法,但这可能是限制访问某些数据的一种简单方法。在紧要关头拒绝访问某个表真的很容易。

    My blog entry about it.

        3
  •  51
  •   chaos    16 年前

    稀疏。从技术上讲,数据关系可能是1:1,但不必为每一行都存在相应的行。因此,如果您有两千万行,并且有一组值只存在于其中的0.5%,那么如果您将这些列推到一个可以稀疏填充的表中,则可以节省大量空间。

        4
  •  27
  •   Tripartio    9 年前

    请注意大多数示例的数据库实现的一个重要特征:没有保留关于1:1关系的历史信息。也就是说,在任何给定的时间点,这些关系都是1:1。如果数据库设计器希望记录关系参与者随时间的变化,则关系变为1:M或M:M;他们失去了1:1的天性。明白了这一点,接下来是:

    • :当一个实体是另一个实体的特定类型时,此类别为。例如,可能有一个员工实体,其属性适用于所有员工,然后是不同的实体,以指示具有该员工类型特有属性的特定类型的员工,例如医生、会计师、飞行员、,这种设计避免了多个空值,因为许多员工没有特定子类型的专门属性。该类别中的其他示例可以是作为超类型的产品,以及作为子类型的ManufacturingProduct和MaintenanceSupply;动物为超型,狗和猫为亚型;请注意,每当您尝试将面向对象的继承层次结构映射到关系数据库(例如在对象关系模型中)时,这就是表示此类场景的关系类型。

    • “老板”关系 ,例如经理、主席、总裁等,其中一个组织单元只能有一个老板,一个人只能是一个组织单元的老板。如果这些规则适用,那么你就有一种1:1的关系,比如一个部门的一位经理,一个公司的一位CEO,等等。“老板”关系不仅仅适用于人。例如,如果一家公司的总部只有一家店铺,或者一个国家的首都只有一个城市,则会发生同样的关系。

    • 例如,一名员工一次只能分配一辆公司汽车(例如,每个卡车司机一辆卡车,每个出租车司机一辆出租车等)。最近一位同事给了我这个例子。

    • 结婚

    • 匹配预订 :当进行唯一预订,然后作为两个单独的实体履行时。例如,汽车租赁系统可能在一个实体中记录预订,然后在另一个实体中记录实际租赁。虽然这种情况也可以设计为一个实体,但将实体分开可能是有意义的,因为并非所有的保留都得到满足,而且并非所有的租金都需要保留,而且这两种情况都很常见。

    我重复我先前提出的警告,即只有在没有记录历史信息的情况下,这些关系中的大多数才是1:1关系。因此,如果一名员工改变了在组织中的角色,或者一名经理负责另一个部门,或者一名员工被重新分配了一辆车,或者有人丧偶并再婚,那么关系参与者可能会改变。如果数据库不存储有关这些1:1关系的任何以前的历史记录,则它们仍然是合法的1:1关系。但是如果数据库记录了历史信息(比如为每个关系添加开始和结束日期),那么它们几乎都会变成M:M关系。

    历史注释有两个显著的例外:第一,某些关系很少改变,因此历史信息通常不会被存储。例如,大多数IS-A关系(如产品类型)是不可变的;也就是说,它们永远不会改变。因此,历史记录点是没有意义的;这些将始终作为自然的1:1关系来实现。第二,预订与租赁关系分别存储日期,因为预订和租赁是独立的事件,每个事件都有自己的日期。由于实体有自己的日期,而不是1:1关系本身有一个开始日期,因此即使存储了历史信息,它们仍将保持为1:1关系。

        5
  •  21
  •   Walter Mitty    16 年前

    在现实世界中,数据项之间肯定存在1:1的关系。毫无疑问。“是一种”关系通常是一对一的关系。汽车是一种交通工具。 一辆车就是一辆车。一辆车可能就是一辆车。有些车辆是卡车,在这种情况下,一辆车不是汽车。有几个答案涉及这种解释。

    但我想你真正想问的是。。。当存在1:1关系时,是否应该拆分表?换句话说,您是否应该有两个包含完全相同键的表?实际上,我们大多数人只分析主键,而不分析其他候选键,但这个问题略有不同。

    有一个称为6NF的标准化级别。6NF的规范化规则肯定会导致两个表具有相同的主键。6NF比5NF的优点是可以完全避免空值。这对一些(但不是所有)数据库设计者来说很重要。我从来没有费心把一个模式放到6NF中。

    在6NF中,缺失的数据可以用省略的行来表示,而不是在某些列中用NULL表示的行。

    拆分表除了规范化之外还有其他原因。有时拆分表会产生更好的性能。对于某些数据库引擎,您可以通过分区表而不是实际拆分表来获得相同的性能优势。这样做的好处是保持逻辑设计易于理解,同时为数据库引擎提供加速所需的工具。

        6
  •  19
  •   Shane Delmore    16 年前

    我使用它们主要有几个原因。一个是数据变化率的显著差异。我的一些表可能有审计跟踪,我跟踪记录的早期版本,如果我只跟踪10列中5列的早期版本,那么将这5列拆分到一个单独的表上,并在其中使用审计跟踪机制会更有效。此外,我可能有只写的记录(比如会计应用程序)。您不能更改美元金额或其账户,如果您犯了错误,则需要制作相应的记录以注销不正确的记录,然后创建更正分录。我对表有一些约束,强制执行它们不能被更新或删除的事实,但我可能对该对象有一些可延展的属性,这些属性保存在一个单独的表中,不受修改的限制。我做这件事的另一次是在医疗记录应用程序中。有一些访问相关数据在登录后无法更改,还有一些访问相关数据在登录后可以更改。在这种情况下,我将分割数据并在锁定表上放置触发器,在注销时拒绝对锁定表的更新,但允许对医生未注销的数据进行更新。

        7
  •  14
  •   Tom H zenazn    14 年前

    我能想到的最常见的情况是当你有斑点的时候。假设您希望在数据库中存储大型图像(通常,这不是存储图像的最佳方式,但有时约束使其更方便)。您通常希望blob位于单独的表中,以改进对非blob数据的查找。

        8
  •  9
  •   Quassnoi    16 年前

    就纯科学而言,是的,它们是无用的。

        9
  •  9
  •   eleven81    16 年前

    与其使用视图限制对字段的访问,有时将受限制的字段保留在只有特定用户有权访问的单独表中是有意义的。

        10
  •  8
  •   Frederik Gheysels    16 年前

    我还可以考虑使用继承的OO模型,并且必须将继承树持久化到DB。

    在数据库中,您可以有一个“Animal”表,其中包含Animal类的公共字段,Animal表与Bird表有一对一的关系,与Fish表有一对一的关系。

    在这种情况下,不必有一个包含大量可空列的Animal表来保存Bird和Fish属性,当记录表示一只鸟时,包含Fish数据的所有列都被设置为空。

    相反,您在Birds表中有一个记录,它与Animal表中的记录有一对一的关系。

        11
  •  8
  •   HLGEM    16 年前

        12
  •  6
  •   J.T. Grimes    16 年前

    这也是一种扩展已在生产中的表的方法,与“真实”数据库更改相比,该表的(感知)风险更小。在遗留系统中看到1:1的关系通常是在初始设计之后添加字段的良好指示器。

        13
  •  5
  •   nvogel    15 年前

    无法支持引用约束中的强制基数是SQL的严重限制之一。“可延迟”约束实际上并不重要,因为它们只是一种表示约束在某些时候没有强制执行的方式。

        14
  •  5
  •   Tom H zenazn    14 年前

    通常两个独立的对象空间意味着一个或两个可以相乘(x:many)。如果两个物体真的,真的是1:1,甚至在哲学上,那么它更像是一种“是”的关系。这两个“对象”实际上是一个整体对象的一部分。

        15
  •  4
  •   Indeed is Trash    16 年前

    如果将数据用于一种流行的ORM,可能需要将一个表拆分为多个表以匹配对象层次结构。

        16
  •  4
  •   DevelopingChris    16 年前

    我发现,当我建立1:1的关系时,完全是出于系统原因,而不是关系原因。

    例如,我发现将用户的保留方面放在一个表中,并将用户的用户可编辑字段放在另一个表中,这样在逻辑上编写关于这些字段权限的规则就容易多了。

    但你是对的,理论上,1:1的关系完全是人为的,几乎是一种现象。然而,从逻辑上讲,它允许程序和优化更容易地抽象数据库。

        17
  •  3
  •   Ryan Guill    16 年前

        18
  •  2
  •   JohnFx    16 年前

    大多数情况下,它更多地是一种物理结构而非逻辑结构。它通常用于对表进行垂直分区,以利用跨物理设备拆分I/O或其他查询优化,这些优化与隔离访问频率较低的数据或需要比同一对象上的其他属性(SSN、Salary等)更安全的数据相关。

    规定1-1关系的唯一逻辑考虑是某些属性仅适用于某些实体。然而,在大多数情况下,有一种更好/更规范化的方法通过实体提取对数据建模。

        19
  •  2
  •   Michael Riley - AKA Gunny    15 年前

    我所看到的1:1关系的最佳理由是数据库设计的超类型子类型。我基于这个模型创建了一个房地产MLS数据结构。有五种不同的数据源;住宅、商业、多户型、酒店和;土地

    如果客户需要详细搜索,他们必须选择超级子类型,例如PropertyResidential。

        20
  •  1
  •   Mario Mario    15 年前

    在我看来,1:1关系将类继承映射到RDBMS上。 每个继承的类状态都映射到RDBMS上,表B具有1:1的关系 表名ND A还包含一个表示“强制转换”功能的“类型”字段

    马里奥

        21
  •  1
  •   kta    9 年前

    如果有任何显著的性能优势,您可以创建一对一关系表。您可以将很少使用的字段放入单独的表中。

        22
  •  0
  •   Eppz    16 年前

    但在现实世界中,情况往往不同。您可能希望将数据分解以匹配应用程序接口。

        23
  •  0
  •   Hibou57    11 年前

    如果您的数据库中有某种类型的对象,则可能是这样。

    比如在表T1中,C1、C2、C3列之间有一对一的关系。没关系,它是标准化的。现在假设在表T2中,有C1、C2、C3列(名称可能不同,但类型和角色相同),也有一对一的关系。T2也可以,原因与T1相同。

    我认为规范化不符合这一点,这可能是一个超出它的想法:识别对象类型并将相同类型的对象移动到它们自己的存储池中,使用一些表中的一对一关系,以及一些其他表中的一对多关系。

        24
  •  0
  •   Lesly Revenge    8 年前

    出于安全目的,这是不必要的,但是有更好的方法来执行安全检查。想象一下,您创建的钥匙只能打开一扇门。如果钥匙能打开其他任何一扇门,你应该按闹钟。本质上,你可以有“公民表”和“投票表”。公民对存储在投票表中的候选人一票。如果公民一号再次出现在投票表上,那么他们的投票应该是一个警报。请注意,这是一对一的关系,因为我们不是指候选人字段,而是指投票表和公民表。

     Citizen Table
     id = 1, citizen_name = "EvryBod"
     id = 2, citizen_name = "Lesly"
     id = 3, citizen_name = "Wasserman"
    
     Candidate Table
     id = 1, citizen_id = 1, candidate_name = "Bern Nie"
     id = 2, citizen_id = 2, candidate_name = "Bern Nie"
     id = 3, citizen_id = 3, candidate_name = "Hill Arry"
    

    那么,如果我们看到投票表是这样的:

     Voting Table
     id = 1, citizen_id = 1, candidate_name = "Bern Nie"
     id = 2, citizen_id = 2, candidate_name = "Bern Nie"
     id = 3, citizen_id = 3, candidate_name = "Hill Arry"
     id = 4, citizen_id = 3, candidate_name = "Hill Arry"
     id = 5, citizen_id = 3, candidate_name = "Hill Arry"
    

    我们可以说3号公民是一个骗子,他欺骗了伯尼。只是一个例子。

        25
  •  0
  •   symbiont    5 年前

    当您处理来自第三方产品的数据库时,您可能不想更改他们的数据库以防止紧密耦合。但您可能有与其数据1:1对应的数据

        26
  •  -4
  •   Paul W Homer    16 年前

    任何地方都有两个完全独立的实体共享一对一的关系。一定有很多例子:

    个人<-&燃气轮机;牙医 (它是1:N,所以它错了!)

    个人<-&燃气轮机;医生 (是1:N,所以也是错的!)

    个人<-&燃气轮机;配偶

    是的,这些都是非常糟糕的例子,特别是如果我一直在寻找1:1,而不是0或1的两边。我猜我的大脑是错误的:

    所以,我会再试一次。经过一番思考后,我们发现,拥有两个独立实体(就软件而言)的唯一方法就是让它们在更高的分类中同时存在。然后,如果且仅当你陷入一个较低的分解,事物是分开的,也应该分开,但在较高的层次上,它们不能没有彼此而生存。因此,上下文是关键。

    对于医学数据库,您可能希望存储有关身体特定区域的不同信息,将它们作为单独的实体保存。在这种情况下,患者只有一个头,他们需要它,否则他们就不是患者。(它们也有一个心脏和许多其他必要的单一器官)。例如,如果您对跟踪手术感兴趣,那么每个区域都应该是一个独特的独立实体。

    在每种情况下,您都可以将单独的实体生成为一个大记录,但考虑到分解级别,这是错误的。在这些特定的环境中,它们是真正独立的实体,尽管在更高的层次上它们可能并不如此。

    保罗。