仅在主表上作为复合主键

Posted

技术标签:

【中文标题】仅在主表上作为复合主键【英文标题】:Primary Key as composite only on Primary table 【发布时间】:2016-08-09 17:54:29 【问题描述】:

我们的环境中有一张桌子。最近发现,通过对dba想做主键的datetime进行排序,性能得到了很大的提升。由于无法保证日期时间的唯一性,他将曾经是主键的 id 添加到他的新复合键中。

所以有一个主键为 datetime / id 的表,并且聚集索引也是这样定义的。所有 pk / fk 关系仍然正确设置,并且存在于人们期望的 id 到 id 范式中。

主键不平衡可能会出现什么问题?

这一变化大大提高了性能。

但是,在架构中,实际的“主键”是两列。可能会出什么问题?

【问题讨论】:

Why use multiple columns as primary keys (composite primary key)的可能重复 所以这并没有破坏现有的 FK 关系。为什么他不只是在日期时间上放置一个非聚集索引? 保留现有的唯一列作为主键。然后在 datetime 列上创建一个新的 INDEX。您没有提及数据库平台,但如果这是 Sql Server 2008(我相信)或更高版本,您可以选择 INCLUDE 列,这些列将与索引列一起保存。这仍然应该让您接近将日期包含在/包含在聚集索引中的速度。如果您需要更多选项,则应包括数据库平台和版本。 另外,主键的选择应该基于唯一性,而不是基于查询执行速度。假设前者(模式)是正确的,后者(查询)总是可以使用索引进行调整或确保查询结构本身是正确的。 在某些情况下,对 pk 升序以外的数据进行排序是有意义的,具体取决于数据的使用/访问方式。这里就是这种情况。我想知道主键像这样格式错误的二分法。适当的关系存在于数据库中的任何地方......除了表上的示意图定义,它的定义中包含日期时间。 【参考方案1】:

不要那样做!使用这两个字段设置唯一索引。它不必是主键。事实上,如果您希望原始密钥保持唯一,那么这是一个糟糕的主意。

【讨论】:

我不明白将日期添加到唯一 ID 会如何危及唯一性。 @Joe:如果旧PK仅基于id列。但是现在新的 PK 被定义为 id + date 列。 id 列现在允许重复值。这可能是不可取的。 啊,如果 ID 没有唯一索引,那么 ID 可能会重复。我认为这暗示 ID + date 不会是唯一的。我误会了。【参考方案2】:

编辑:这个答案是假设 Sql Server。如果事实证明不是,那么我将删除我的答案。

您没有列出详细信息,因此我将不得不给出一个非常笼统的答案。在我的研究中,我发现大多数人会推荐短主键/聚集索引。

这里真正的关键是您所说的提高性能。它只是一个查询吗?换句话说,此更改是否对该数据的所有操作产生有益的或至少微不足道的性能影响?用户界面、所有报告等。还是这个抢劫彼得付钱给保罗?

如果这是一个大多数报告都基于日期的报告数据库或数据仓库,我可以理解为什么人们可能会建议设置聚集索引以使所有报告或最重要的报告受益.

在我能想到的任何其他情况下,非聚集索引将提供几乎相同的水平或性能提升,而不会增加 PK 的大小,PK 的大小也用于所有查找(读取的字节数越多 = 性能越慢)因为在您的数据页上占用更多空间。

编辑: 这篇文章比我能更好地解释这个话题。

https://www.simple-talk.com/sql/learn-sql-server/effective-clustered-indexes/

【讨论】:

我们确定 OP 使用的是 SQL Server 吗? 好点,我以为我只是在浏览 Sql Server 问题。【参考方案3】:

您目前看到的性能优势(如果是真的)是由于与主键关联的聚集索引,而不是主键本身。如果您对当前索引感到满意,但担心唯一性,您应该将唯一的 datetime / id 保留为您的聚集索引,但恢复为旧的唯一 id 作为主键。

这也解决了引用此主键的其他表可能需要创建可能不适当的日期时间列来创建外键关系的问题。

【讨论】:

正是...聚集索引部分我没有质疑。在这种情况下,这显然是有益的。我不知道他为什么不创建聚集索引并单独留下主键。他看到了性能的提升。可以通过他的所作所为来衡量。连接在那里是因为所有的 id 都是相同的。 fk 约束也是如此(仅指向 id)。唯一的区别是表定义中包含的日期列。

以上是关于仅在主表上作为复合主键的主要内容,如果未能解决你的问题,请参考以下文章

使用复合主键在联结表上设置外键约束

MySQL 中的复合主键性能缺陷

为啥要用多列作为主键(复合主键)

具有复合键的一对多注释映射

什么是复合主键

Yesod中的复合主键