【问题标题】:Composite Primary key verses one column based primary key复合主键与基于一列的主键
【发布时间】:2010-08-20 21:46:33
【问题描述】:

我已经浏览了链接:

Database Design: Composite key vs one column primary key

我的问题:

对于一个永远不能作为外键引用到任何其他表的表,在插入/更新基于单列的主键与多列/复合列主键方面,+ve / -ve 方面是什么?

谢谢

【问题讨论】:

    标签: database-design


    【解决方案1】:

    是的,多列主键仍然是一个不好的选择,如果:

    • 您的主键也是集群键
    • 您的表还包含其他非聚集索引

    因为:

    • 集群键(例如单个 INT 列或复合键)中的值将添加到每个非聚集索引中的每个条目

    因此:如果您有一个 200 字节大小的复合主键,并且您的表上有一些非聚集索引,那么您将在 SQL 上浪费 大量 内存服务器 - 不仅在(相对便宜的)磁盘上,而且在 SQL Server 主内存中(通常不那么便宜)。

    除了浪费空间之外,您的性能也会滞后,因为更大的索引意味着相同操作的磁盘 I/O 更多。

    一般情况下:在您从不需要引用该表(实际上永远不会,甚至将来也不会)并且没有其他表的情况下才在表上使用复合主键 该表上的非聚集索引。

    【讨论】:

    • 您已经给出了一些为什么不在 SQL Server 中使用过大聚集索引的理由。然而,这些问题与主键无关。聚集索引和键不是一回事——即使在 SQL Server 中也是如此。此外,复合键很可能比单个属性键小 - 因此单独的大小并不是避免复合键的论据。
    • @dportas:严格来说,你是对的。但是 SQL Server 中至少 90% 的主键也是集群键 - 主要是因为许多开发人员根本不了解集群键,他们的主键自动成为他们的集群键。
    • 我有一个表,其主(集群)键是日志表的用户 ID 和时间戳。我认为这很好,因为它是表上的 only 索引/键。它可以快速为单个用户生成总和,因为 UserID 是该聚集索引(主键)中的 first 列,并且在索引中包含时间戳可确保它是唯一的。听起来不错?
    • @Triynko:取决于这两列的数据类型,以及它们的特征:它们可以改变吗? NOT NULL 是唯一的吗?
    • UserID 是 bigint,Timestamp 是 datetime2(7),所以它们是非空的,固定长度的,并且永远不会改变。在系统非常年轻的时候,我们曾经使用“用户名”作为主键,但我们需要能够更改它,因此我没有向这个可变长度键添加级联更新,而是通过创建一个固定长度的整数 UserID 永远不会改变,并且仅用于作为 PK/FK 的数据库表之间的关系。
    【解决方案2】:

    您怎么可能绝对确定您的密钥“永远不会被 FK 引用”?

    您的属性组合确实是独一无二的(否则您不会考虑将其设为“主键”)。

    因此,您的属性组合是识别表中描述的真实事物的有效方法。

    说这永远不会被 FK 引用就等于说“没有关于此类事物的额外信息将永远与业务相关”。你怎么可能知道?

    【讨论】:

    • 亲爱的,感谢您的及时回复,但我仍然遵守我的“永远不会被 FK 引用”的声明,因为特定表在我的数据库中的表层次结构中最低。如果你需要,那么我会给你一个确切的例子。
    • 很容易将其设计为永远不会被 FK 引用,因为通过设计某些类型的信息是独立的和最终的。例如,具有 UserID,Timestamp 的复合集群主键的日志表是唯一的,并且首先使用 UserID 进行集群,因此可以以最少的 I/O 快速检索单个用户日志。没有其他表需要引用这样的日志条目/键的原因是因为它在设计上是自包含的。换句话说,没有新的/外部的/额外的信息需要在单独的表格中引用或添加到该行。
    【解决方案3】:

    业务要求(数据完整性要求)应该是决定要实施哪些密钥的因素。对一个属性强制唯一性显然与对多个属性强制不同,因为在一种情况下允许的重复项在另一种情况下不允许(当然,除非您实现 both 键)。

    请注意,marc 的回答仅适用于聚集索引,不适用于主键。它们不是同一件事。他的回答也是针对 SQL Server 的。

    【讨论】:

    • 是的,我的回答是特定于 SQL Server 的,是的,它适用于集群键 - 但默认情况下,您的 SQL Server 主键 ARE 集群键 - 除非您明确转关闭 - 可能绝大多数开发人员不会这样做......
    • 亲爱的大家,我对以上所有回复感到困惑。如果在我的情况下复合键是主键并且它也将具有聚集索引并且此表永远不会用作 FK 并且没有其他非聚集索引,那么 wat 将影响此表中的插入和更新。这里需要提一下,这个表会有大量的数据。
    • @ibrar:是的,当然有影响。这种约束的目的正是为了防止不正确的更新或插入。显然,执行此检查存在开销,但如果您不想检查唯一性,那么您根本不会实施约束。因此,是在单列还是多列上实现它不是与性能相关的问题——这取决于您想要实现的目标。我不知道索引中的单列或多列之间的性能存在任何一般差异,但这可能取决于很多因素,因此我建议您自己测试一下。
    【解决方案4】:

    在这个问题上有两种相互竞争的哲学。

    我本人坚定地支持对某些表使用复合主键。

    当我设计一个数据库时,我使用 ER 建模在一个地方收集信息需求。数据库提供的每个值都是属性的一个实例,每个属性描述一个主题实体或两个或多个主题实体之间的关系。外键不进入分析阶段。

    在开始数据库设计之前,我从应用程序的角度决定如何识别每个实体。这些将给我我的主键。每个描述实体的表都有一个简单的主键,即实体的标识符。简单的关系(二进制、多对一)不需要自己的表。每个描述复杂关系的表都有一个由参与实体的主键组成的复合主键。

    外键以显而易见的方式插入。好吧,至少对我来说很明显。这提供了 3NF 中的初始表设计,并且可能更高。表设计可能会通过进一步的规范化或其他与规范化不兼容的设计模式(所谓的非规范化)而改变。但这是餐桌设计的第一次削减。

    就性能和数据完整性而言,这种设计实践与主流实践产生了不同的结果。普遍的做法是在每个表的第一列中放置一个名为“id”的自动编号列。此列成为主键。

    本质上,这种做法使用 SQL 表结构来模仿数据的图形模型,即使它看起来像一个关系模型。 id 列本质上是行地址的代理。数据的图形模型有一个优点和一个缺点。如果需要,请提供更多信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-19
      • 1970-01-01
      • 2011-06-11
      • 2017-12-29
      • 1970-01-01
      相关资源
      最近更新 更多