Sql 复合主键

Sql 复合主键,sql,database,primary-key,composite,Sql,Database,Primary Key,Composite,我正在设计一个数据库,用于存储来自多个不同来源的数据。我存储的实例由原始源分配唯一的ID。我存储的每个实例都应该包含有关它来自的源的信息,以及它与此源关联的ID 作为一个例子,考虑下面的表格来说明问题: ---------------------------------------------------------------- | source_id | id_on_source | data | ------------------

我正在设计一个数据库,用于存储来自多个不同来源的数据。我存储的实例由原始源分配唯一的ID。我存储的每个实例都应该包含有关它来自的源的信息,以及它与此源关联的ID

作为一个例子,考虑下面的表格来说明问题:

----------------------------------------------------------------
| source_id | id_on_source | data                              |
----------------------------------------------------------------
| 1         | 17600        | ...                               |
| 1         | 17601        | ...                               |
| 2         | 1            | ...                               |
| 3         | 1            | ...                               |
----------------------------------------------------------------
请注意,虽然每个源上的
id\u
都是唯一的,但对于不同的源,可以找到相同的
id\u

我对关系数据库有很好的理解,但我远不是专家,甚至不是有经验的用户。我在这个设计中面临的问题是我应该使用什么作为主键。数据似乎指示使用复合主键
(source\u id,id\u on\u source)
。在谷歌搜索了一下之后,我发现了一些关于复合主键利弊的激烈争论,这让我有点困惑

该表将与其他表具有一对多关系,因此将在其他表的外键中引用

我并不局限于一个特定的
RDBMS
,我也不确定它是否对这个参数有影响,但假设我更喜欢使用
SQLite
MySQL


在这种情况下使用复合外键的优缺点是什么?你更喜欢哪一种?

我个人觉得复合主键很痛苦。对于要加入“源”表的每个表,您都需要添加source_id和id_on_source字段

我将在sources表上创建一个标准的自动递增主键,并在source\u id和id\u source列上添加一个唯一的索引

这样,您就可以将源表的id作为外键添加到其他表中


一般来说,我还发现在许多框架和工具产品中对复合主键的支持充其量是“零碎的”,在其他框架和工具产品中是不存在的

复合键很难管理,加入速度也很慢。因为您正在构建摘要表,所以请使用代理键(即自动增量/标识列)。将自然键列保留在那里

这也有很多其他好处。首先,如果您与一家公司合并,并且他们有一个相同的源,但是重用了密钥,那么如果您不使用代理密钥,您将遇到麻烦


这是数据仓库领域广为认可的最佳实践(这是一项比您正在做的工作大得多的工作,但仍然相关),而且理由充分。代理提供数据完整性和快速连接。使用自然密钥可能会很快被烧坏,因此不要将其作为标识符,而只能在导入过程中使用它们。

有些人建议您使用全局唯一ID(GUID):。如果该值在创建时全局唯一,则无需添加源id使其唯一



虽然uniqueid是一个很好的主键,但我同意通常最好使用不同的、自然的(不一定是唯一的)键作为聚集索引。例如,如果uniqueid是标识员工的主键,则可能希望将聚集索引作为部门(如果select语句通常检索给定部门内的所有员工)。如果您确实希望使用unqiqueid作为聚集索引,请参阅函数:这将创建顺序uniqueid值,该值(顺序)具有更好的聚集性能。

我相信组合键可以创建非常自然和描述性的数据模型。我的经验来自Oracle,我认为在创建复合PK时没有任何技术问题。事实上,任何分析数据字典的人都会立即了解表的某些内容。在您的情况下,很明显,每个源的id必须在源上具有唯一的id


自然键的使用通常会引起激烈的争论,但我的同事从良好的数据模型角度来看喜欢自然键。

添加额外的ID列将使您不得不强制执行两个唯一性约束,而不是一个


在其他引用表中使用该额外的ID列作为外键,而不是自然出现的键,将导致您必须进行更多的联接,也就是说,在所有情况下,您都需要原始soruce_ID加上源上的ID以及引用表中的数据。

您有一个业务需求,即这两个属性的组合是唯一的。因此,在这两个属性上应该有一个
唯一的
约束。无论您是否将
UNIQUE
constraint称为“primary”,它实际上只是一种偏好,除了文档之外没有太大影响

唯一的问题是,是否添加一个额外的列并将其标记为唯一。我认为这样做的唯一原因是性能,这是一个合理的理由


就我个人而言,我不喜欢将每个数据库本质上转换为一个图的方法,其中生成的列本质上是指针,而您只是从一个遍历到下一个。我认为这抛弃了关系系统的所有伟大之处。如果你退一步想一想,你是在介绍一堆对你的业务毫无意义的专栏。您可能会对my.

感兴趣。我使用复合主键的唯一时间是当该键的高阶部分是另一个表的键时。例如,我可以创建一个主键为OrderId+LineNumber的OrderLineItem表。由于对OrderLineItem表的许多访问将是“order join OrderLineItem using(orderid)”或其变体,因此这通常很方便。在查看数据库转储时,它还可以很容易地确定哪些行项目连接到了什么顺序

正如其他人所指出的,复合键在大多数其他情况下都是一个难题,因为