【问题标题】:foreign key constraints on primary key columns - issues?主键列上的外键约束 - 问题?
【发布时间】:2010-06-04 05:39:38
【问题描述】:

从性能/索引/数据管理的角度来看,使用子级上的主键作为外键创建表之间的一对一关系与子级上的纯代理主键相比有哪些优点/缺点?第一种方法似乎减少了冗余并很好地隐式约束了一对一,而第二种方法似乎受到 DBA 的青睐,即使它创建了第二个索引:

create table parent (
     id integer primary key, 
     data varchar(50)
)

create table child (
     id integer primary key references parent(id), 
     data varchar(50)
)

纯代理键:

create table parent (
     id integer primary key, 
     data varchar(50)
)

create table child (
     id integer primary key,
     parent_id integer unique references parent(id), 
     data varchar(50)
)

这里感兴趣的平台是 Postgresql、Microsoft SQL Server。

编辑:

以下是来自实际 DBA 的基本想法。主要关注的是子表上的索引碎片。假设将主键为 1-1000000 的记录插入到父表中,而子表中没有任何内容。稍后,临时操作开始使用与父表中的行相对应的行填充子表,但顺序是随机的。令人担忧的是,这会导致插入时出现页面拆分,导致索引碎片,并导致删除时出现“瑞士奶酪”效应。我承认这些不是我非常熟悉的术语,在谷歌上搜索它们时,这些点击似乎都与 Microsoft SQL Server 相关。这些是特定于 MS 的问题吗(即 PG 的 ANALYZE 等是否缓解了 PG 上的问题)?如果是这样,那么这就是使用像 Postgresql 这样的数据库的另一个原因。

【问题讨论】:

    标签: sql sql-server postgresql


    【解决方案1】:

    如果是严格的 1-1 关系,我认为没有理由不使用第一个选项。

    第二个选项提供了一些灵活性,可以稍后使其成为一对多关系,这可能是 DBA 可能偏爱该选项的原因。

    【讨论】:

    • 特别是如果您有第一个子表是父表的子表,那么稍后更改为一对多关系可能会非常痛苦。您必须删除唯一约束并添加一个键,然后更新所有子表以使用新键。如果你从一开始就使用代理键,你所要做的就是删除唯一索引,然后添加一个常规索引。另一方面,有些表永远不可能成为一对多的,在这种情况下,我会不使用代理键。
    【解决方案2】:

    首先,如果你有一个 1:1 的关系,那么一个表的主键也代表另一个表的外键是没有问题的,事实上我建议这是首选方法。

    其次,对于任何 1:1 关系,第一个问题显然应该是是否需要这种关系,因为通常您可以简单地将子表中的列包含到主表中。也就是说,有时一对一的关系显然是有意义的。

    【讨论】:

    • 有一系列一对一的,主要是关于这些表相互独立更新,每次更新都会导致一行被写入历史表。因此,历史表反映主表非常合适。
    • @zzzeek - 好的。如果是这种情况,那么我仍然建议为子表的 PK 创建 FK。这样做的一个好处是,在标准图中,很明显这种关系是 1:1,因为双方都指向一个 PK。
    猜你喜欢
    • 2013-08-12
    • 2020-07-09
    • 1970-01-01
    • 2020-03-16
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 2020-06-12
    相关资源
    最近更新 更多