【问题标题】:Why Composite Primary key when I can use Single Primary key with Unique constraints on composite columns?当我可以在复合列上使用具有唯一约束的单个主键时,为什么要使用复合主键?
【发布时间】:2021-09-17 15:54:34
【问题描述】:

我正在考虑将表架构从单个主键更改为复合主键。

此更改将影响我的许多表以及为查询此类表而编写的 SQL 语句(尤其是联接查询)。

在对复合键方法的好处进行了一些研究后,我发现一个主要卖点是它用于强制复合列的唯一性。

但是,我仍然可以保留单个主键表,然后添加唯一约束以强制复合列的唯一性,如下所示:

create table ... (
 id primary key not null,
 column1 ...
 column2 ...
 .
 .
 columnN ...
 unique(column1, column2) // added this line to my existing tables
)

现在回答问题:

这两种方法有什么好处?

显式定义复合主键或在复合列上使用具有唯一约束的单个主键。为什么?

【问题讨论】:

  • id 字段是否有意义?换句话说,它只是提供唯一整数的自动增量的某种变体,还是具有更高层次的含义?为什么你觉得需要做出改变?有没有一个PK没有提供的东西?
  • 尽量使您的 PK 尽可能简单 - 因此,如果单列就足够了 - 始终倾向于使用此方法而不是复合 PK。它使从其他表加入变得更加容易!
  • 先想想应该怎么做。哪些列唯一标识您的行? ID 还是 ID+column1+column2?此外,PK(id)+UC(c1, c2) 与 PK(id, c1, c2) 不同。有关更理论的观点,请查看此。我认为示例部分非常有趣:en.wikipedia.org/wiki/Database_normalization
  • 请将回复作为更新添加到您的问题中,这样其他人就不必搜索 cmets。你在我的评论中看到我的其他问题了吗?它们是您在第一次阅读时可能没有看到的事后想法。
  • 我认为,如果你想成为唯一的 2 列,请创建一个唯一索引(约束)。这是最好的解决方案。如果您进行复合 PK,则必须更改整个数据库中的连接,并重写/重新创建 FK 列!并重复列。

标签: sql database postgresql database-schema


【解决方案1】:

您不需要主键来强制唯一性。您可以改用unique 约束或索引。

我不喜欢复合主键。以下是一些原因:

  • 所有外键引用都必须包括所有键的正确顺序和匹配类型。这使得定义这些表稍微麻烦一些。
  • 由于复合键包含在所有引用表中,这些表通常更大,这会导致性能更差。
  • 如果您决定要更改其中一个组件键的类型——比如将字符串的长度或int 更改为numeric——您必须修改大量的表格。
  • 连接表时,必须包含所有键。如果你错过了一个。 . .好吧,代码在语法上是正确的,但结果是错误的。

在某些情况下可以接受复合键,例如没有外键引用的表。即使在这些情况下,我也使用合成键,但我完全理解另一个角度。

【讨论】:

  • “另一个角度”:支持代理键和索引是有成本的。例如。我认为在一般情况下,当自然键为 int+date(4+4 字节)时,很难用 uuid(16 字节)来证明代理是合理的——我看到了很多这样的例子。
  • @AlexYu 。 . .有趣的。除非业务目的需要,否则我不会推荐主键使用 UUID。整数效率更高。
  • UUID 在分布式系统中很有意义。但是在bigint 甚至int 就足够的情况下,我看到了很多。也许是 ORM 代码生成器的结果 - 无论如何它总是痛苦和痛苦
  • “另一个视角”扩展:stackoverflow.com/a/69232737/1168212
【解决方案2】:

我将从 Gordon Linoff 的“其他视角”mentioned 发言。

一般来说,我是“专业”复合键。

我认为合成键是一种经常被过度使用的优化技术,有时它变成了一种没有任何优点的悲观化,只是因为程序员习惯了它。

过度使用合成密钥的示例

  • 有一个表对int(4 字节)和date(4 字节)字段具有唯一约束
  • 它们永远不会改变
  • 但无论如何,有人添加了一个带有随机值的uuid(16 字节)字段
  • 并在其上定义一个 PK

我们来分析一下:

  • 算术:每行添加 16 个字节 + 索引成本不是优化,而是悲观
  • 代码:我不认为添加一个AND 真的很痛苦
  • 语义:自然键具有一些商业价值,合成键 - 不是

不要仅仅为了争论而认为这是一个虚构的反例 - 我看到了很多这样的合成键。

注意事项:

A. uuid 键可能是合理的 在某些情况下,我在https://stackoverflow.com/a/69213338/1168212 中描述了它们

B.即使是 bigint(8 字节)代理键也好不了多少:它是每行 8 字节 + 索引成本。

C.危险场景:所有应用程序代码都是围绕合成密钥编写的,然后有一天有人偶然发现违反了唯一约束,他想到了一个“聪明”的想法,如何“修复”它:删除唯一约束!麾!应用程序开始工作!严酷的真相是后来才意识到的。

别笑:我多次看到后者。

合成密钥的可行案例

A. 许多字段处于唯一约束。我认为:2 个字段还可以,3 个一般,4-5 个更多 - 写所有 ANDs 变得很麻烦,而且代码容易出错,所以我会考虑合成密钥

B. 唯一约束中的字段长度很大。例如。您在唯一约束中结合了 varcharuuid,合成整数键类似于优化技术

C. 唯一约束中的数据经常更新。然后合成密钥

D. 唯一约束的规则可以在系统的生命周期内改变。您知道实体是相关的,但您希望该规则会随着新的业务需求而改变。然后合成密钥将解决这个问题。

E. 数据仓库设计于Dimensional Modelling。此类数据库的设计从代理键的设计开始

F。 其他要求,例如需要对数据库中的所有实体进行细粒度授权

总结

我认为不存在适用于所有情况的通用规则。

合成密钥有其成本:

  • 不要拘泥于一条规则
  • 分析需求
  • 做数学题
  • 从编码角度考虑

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 2011-02-07
    • 2011-01-17
    • 1970-01-01
    • 1970-01-01
    • 2016-11-06
    • 1970-01-01
    相关资源
    最近更新 更多