使用复合/复合主键的缺点是啥?

Posted

技术标签:

【中文标题】使用复合/复合主键的缺点是啥?【英文标题】:What are the down sides of using a composite/compound primary key?使用复合/复合主键的缺点是什么? 【发布时间】:2008-09-20 06:38:01 【问题描述】:

使用复合/复合主键有什么缺点?

【问题讨论】:

【参考方案1】:
    可能会导致更多规范化问题(2NF,“请注意,当 1NF 表没有复合候选键(候选键由多个属性组成)时,该表会自动处于 2NF ") 更多不必要的数据重复。如果您的复合键包含 3 列,则需要在每个表中创建相同的 3 列,用作外键。 通常可以借助代理键 (read about their advantages and disadvantages) 避免 我可以想象复合键的一个很好的场景——在一个表示 N:N 关系的表中,比如学生 - 班级,中间表中的键将是 (StudentID, ClassID)。但是,如果您需要存储关于每对的更多信息(例如班级中学生所有分数的历史记录),那么您可能会引入代理键。

【讨论】:

代理键!暂时想不起来这个词了,谢谢! :)【参考方案2】:

拥有复合键本身并没有错,但理想情况下,主键应该尽可能小(就所需的字节数而言)。如果主键很长,那么这会导致非聚集索引膨胀。

请记住,主键中列的顺序很重要。第一列应尽可能具有选择性,即尽可能“独特”。第一列上的搜索将能够查找,但仅在第二列上的搜索必须进行扫描,除非第二列上还有非聚集索引。

【讨论】:

【参考方案3】:

我认为这是合成密钥辩论的专业化(是否使用有意义的密钥或任意合成主键)。出于多种原因,我几乎完全站在了这场辩论的综合关键方面。以下是一些比较相关的:

您必须保留受抚养的孩子 外键末尾的表格 最新。如果你改变 主键之一的值 字段(可能发生 - 见 下面)你必须以某种方式改变 所有从属表,其中 他们的PK值包括这些 字段。这有点棘手 因为改变键值会 使 FK 关系无效 子表,所以你可以(取决于 关于约束验证选项 在您的平台上可用)必须 使用复制等技巧 记录到一个新的并删除 旧记录。

在深度模式中,键可以获得 相当宽 - 我看过 8 列 一次。

主键值的更改可以 在 ETL 中难以识别 进程加载系统。 我曾经有机会看到的例子 看到是一个 MIS 应用程序 从保险中提取 承保制度。一些 政策条目将是 被客户重复使用,改变 策略标识符。这是一个 的主键的一部分 桌子。当这种情况发生时 仓库负载不知道是什么 旧值因此无法匹配 新的数据给它。开发商 不得不通过审计进行搜索 日志以识别更改的值。

非合成主键的大多数问题都围绕记录的 PK 值更改时的问题。非综合值最有用的应用是打算使用数据库模式的地方,例如 M.I.S.报告作者直接使用表格的应用程序。在这种情况下,为方便起见,可以合理地将具有固定域的短值(例如货币代码或日期)直接放在表格上。

【讨论】:

【参考方案4】:

在那些对自然复合键具有唯一非空约束的情况下,我会推荐生成的主键。

如果您使用自然键作为主键,那么您很可能必须在外键引用中引用这两个值,以确保您识别的是正确的记录。

【讨论】:

【参考方案5】:

以具有两个候选键的表为例:一个简单(单列)和一个复合(多列)。在这种情况下,您的问题似乎是,“如果我选择将一个键提升为'主'并选择复合键,我可能会遭受什么不利影响?”

首先,考虑一下你是否真的需要提升一个键:“SQL 中PRIMARY KEY 的存在似乎是某种历史上的意外。根据作者 Chris Date 的说法,SQL 最早的化身没有”没有任何关键约束,PRIMARY KEY 只是后来才被添加到 SQL 标准中。标准的设计者显然是从发明它的 E.F.Codd 那里取来的,尽管当时 Codd 最初的概念已经被抛弃了!(Codd 最初提出外键只能引用一个键——主键——但这个想法被遗忘和忽略了,因为它被广泛认为是一个毫无意义的限制)。” [来源:David Portas' Blog: Down with Primary Keys?

其次,你会应用什么标准来选择表中的哪个键应该是“主键”? 在 SQL 中,键 PRIMARY KEY 的选择是任意的并且是特定于产品的。在 ACE/Jet(又名 MS Access)中,两个主要且经常相互竞争的因素是您是否要使用 PRIMARY KEY 来支持磁盘上的集群,或者您是否希望包含键的列在“关系”图片中显示为粗体MS Access 用户界面;我认为索引策略胜过漂亮的图片是少数派 :) 在 SQL Server 中,您可以独立于 PRIMARY KEY 指定聚集索引,并且似乎没有提供特定于产品的优势。唯一剩下的优势似乎是您可以在 SQL DDL 中创建外键时省略 PRIMARY KEY 的列,这是一种 SQL-92 标准行为,无论如何对我来说似乎没什么大不了的(也许是另一个他们添加到标准中的东西之一,因为它是 SQL 产品中已经广泛使用的功能?)所以,这不是寻找缺点的情况,而是,您应该看看有什么优势,如果有的话,你的 SQL 产品会给出PRIMARY KEY。换句话说,选择错误键的唯一缺点是您可能会错过给定的优势。

第三,您是否暗示使用人工/合成/代理键在您的物理模型中实现逻辑模型中的候选键,因为您担心如果您在外键中使用自然键和表连接?这是一个完全不同的问题,很大程度上取决于您对 SQL 中自然键问题的“宗教”立场。

【讨论】:

【参考方案6】:

需要更多的特异性。

太过分了,它可能会使插入(每个键都必须存在)和文档过于复杂,如果不完整,您的连接读取可能会受到怀疑。

有时它可以指示有缺陷的数据模型(复合键真的是数据所描述的吗?)

我不相信会有性能成本……它很容易出错。

【讨论】:

好吧,我会说性能成本可能会上升,因为您必须保留 X 个主键元素的索引,但我只是为了完整性而提及这一点。 好吧,索引会更大,所以是的,你会为读取支付更多费用。 其实这让我想起了。某些复合索引仅在索引搜索 (A, B) 中包含第一个键时才有效。如果您只使用 B 那么它必须在没有索引的情况下进行完整搜索。 Postgres 就是这样,它也可能取决于索引类型,但我不确定。所以它可能会影响读取。呵呵:)【参考方案7】:
    当您将其放在图表上时,可读性会降低 当你在查询连接上使用它时 可读 当你在外键上使用它时 你必须添加一个检查约束 关于所有属性必须是 空或不空(如果只有一个是 null 未检查密钥) 使用时通常需要更多存储空间 作为外键 某些工具不能管理复合 键

【讨论】:

【参考方案8】:

使用复合主键的主要缺点是你会混淆典型的 ORM 代码生成器。

【讨论】:

我在 SO 上问了这个问题,一个流行的回答是 NHibernate 与复合 PK (***.com/questions/218100/…) 配合得非常好。

以上是关于使用复合/复合主键的缺点是啥?的主要内容,如果未能解决你的问题,请参考以下文章

复合主键的一部分可以用作另一个表的复合主键的一部分吗?

用于更改表添加复合主键的批量 SQL 语句

Cassandra 中使用复合主键的慢插入时间

SQL:选择另一个表中没有复合主键的条目

mysql外键仅引用复合主键的一部分

Mysql复合主键的索引