嗨,我有一个父表,它有 ID 和其他一些列,还有一个子表,它有很多基于这个 ID(外键)的值。我想用一个主键创建表,该主键是序列,这个父表 ID 作为外键,但后来我发现我还有一个外键 EMPID,它的组合提供了唯一性。即使对于检索和批量更新,我也可以简单地使用这两个 FK 的组合。所以我仍然需要使用序列生成器来牢记数据库性能还是只删除主列。
5 回答
如果您确定永远不需要或想要引用该序列生成的密钥(并且没有其他对象将引用该 ID),那么只要您可以保证您的组合外键将始终提供唯一的组合。
如果您确实注意到性能问题,您可能希望对作为外键的列(现在组合起来充当主键)建立索引,以提高查询这些列的性能。
关系纯粹主义者会告诉您,您根本不需要顺序生成的 ID 列 - 每个表中的主键应该是共同唯一标识每一行的列组合。(如果有多个列组合执行此操作,则选择一个作为主键,并使用唯一约束强制其他列)。
如果这些列中的一个或多个列很大或笨拙,或者此类列的数量使主键本身很大且笨拙,则这种情况往往会出现问题。这就是我与关系纯粹主义者不同的地方,说继续,添加一个代理键(这就是 IDENTITY/Sequence ID 列更恰当地称为)。但请确保其他键仍在使用唯一性约束强制执行。
可以肯定的是,没有理由必须在表中包含一个 ID 列。如果每个表都必须有一个,您会认为 DB 产品会自动为您提供它。
(我会把它放在评论中,但它太长了。)
理论上主键不必是不可变的;然而,在现实世界中,拥有可变主键是一场噩梦,原因有两个:
- 随着关系模型的增长,每个子表都必须包含父主键的每一列。
- 与所有唯一约束一样,主键由索引强制执行。
- 一些 DBMS 的索引中根本没有足够的列来满足这种自然键构造。
- 同样,索引键的数据长度也存在长度要求。
- 最后,可变主键必须在整个系统中级联。
简而言之:
如果您的关键值可能会改变
-- 信用卡号或帐号是一个糟糕的主键,因为它可以改变,而名字是一个非常糟糕的选择
或者
你有任何通过外键依赖于这个表的数据(当需要时很容易重构它)
然后
创建一个代理键作为主键。很高兴您找到了表的自然键;也对这些列施加唯一约束。
为了保持一致性,我喜欢在我的所有表中都有一个代理键(一个自动生成的标识/排序的主键)。开销是最小的,它允许与数据库结构一致的程序员接口。
我想说,最好对数据库设计施加所有限制和约束。它们很有用,至少如果您在 Oracle DB 中。参考Tom Kyte(askTom 成名)。据他介绍,这些引用/约束用于决定执行路径。
有趣的是,约束对于查询优化有多么重要。许多人认为约束是数据完整性的事情,这是真的——他们是。但是在确定最佳执行计划时,优化器也会使用约束。优化器将其作为输入。
- 要优化的查询
- 所有可用的数据库对象统计信息
- 系统统计信息(如果可用)(CPU 速度、单块 I/O 速度等——关于物理硬件的指标)
- 初始化参数
- 约束
它最终可能会产生更好的性能。