复合主键?还是具有唯一复合索引的自动增量主键? [关闭]

Posted

技术标签:

【中文标题】复合主键?还是具有唯一复合索引的自动增量主键? [关闭]【英文标题】:Composite primary key? Or an auto increment primary key with unique composite index? [closed] 【发布时间】:2020-10-28 09:58:00 【问题描述】:

我有两个名为 StudentCourse 的表以及一个名为 StudentCourse 的连接表。 StudentCourse 都有一个自动递增整数 Id

StudentCourse 表最多有 10,000 条记录(不会更多!),我将在大多数情况下使用此表来选择一些数据。 插入性能现在不是我关心的问题,我只想快速获取数据!

我的查询形式为:

select * from studentcourse where studentid == sid and courseid == cid
select * from studentcourse where studentid == sid

以下哪种实现方式更好?为什么?它总是比另一个更好还是取决于? 对我的 senario 有更好的解决方案吗?

1:使用 StudentCourse 的自动递增 Id 列作为主键,并设置一个唯一的复合索引,如 (StudentId, CourseId).

2:使用复合主键,如 (StudentId, CourseId)

3:创建没有主键的表,只使用像 (StudentId, CourseId) 这样的唯一复合索引。


更新

如果我们有一些仅在我们有关系时才重要的其他属性怎么办!将ScoreGrade 视为StudentCourse 表中的第三列。在这种情况下我们应该使用第一个选项吗?我的意思是假设我们正在使用 ORM,并且我们应该在我们的 Student 类(实体)中有对 StudentCourse 类(实体)的引用。

【问题讨论】:

就像下面的两个答案一样,我会选择#2。请记住,索引按适当的列对数据进行排序,因此对于聚集索引(通常默认情况下带有主键),您通常希望第一列是您最常过滤的列。但是,在这样的表上,我经常有一个相反顺序的非聚集索引(例如,CourseId, StudentID),所以如果你从其他方式进行查询(例如,哪些学生在 CourseID 421 中?)它还有一个可以使用的索引。 更新后:这里的关键部分是聚集索引在您需要时为您提供帮助。默认情况下,某些数据库(例如 SQL Server)使您的聚集索引与 PK 相同。如果需要(例如,选项 1),您可以使用与 PK 不同的聚集索引,特别是如果您可以在需要的聚集索引中有重复项。在StudentID, CourseID 上使用聚集索引的优势在于,它有助于查找特定学生或一组学生的课程记录。建议brentozar.com/training/think-like-sql-server-engine - 它真的帮助了我。 【参考方案1】:

2 是最好的。

它比 1 好,因为它少了一个索引(因此占用的空间/缓存更少,索引维护成本更低)。代理键(如Id)在联结表中通常是无用的。

这可能比 3 更好,具体取决于您的 DBMS:某些 DBMS 不允许您在唯一索引上(仅在主键上)cluster 表1支持>。即使在允许它的 DBMS(如 SQL Server)上,我也会选择 1,因为它更直接且语法更简单。


1 有些不允许您从外键引用唯一索引(只是主键或唯一约束),尽管这可能与这里无关。如果是,那么您会考虑使用代理键 Id

【讨论】:

【参考方案2】:

前两个选项很好。重要的部分是在(studentid, courseid) 上有一个唯一索引。唯一性保证了数据的完整性(同一个学生不能两次上同一门课),索引提高了查找的效率。

是否应该有代理主键有待讨论。如果您需要以某种方式唯一标识每条记录(例如:从另一个表中引用该表),单列主键可能会派上用场。

我不推荐第三个选项,因为它不强制完整性约束。

最后:在大多数数据库中,索引中键的顺序确实很重要。对于您显示的两个查询,您希望 studentid 在索引中的第一位,因此仅在此列上过滤的查询仍然可以使索引受益。

【讨论】:

以上是关于复合主键?还是具有唯一复合索引的自动增量主键? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

复合索引主键与唯一自增主键

MySQL 死锁与复合主键和触发自动增量

如果自动增量字段不是第一个,jOOQ 可以支持复合主键吗

Postgres中唯一的部分复合主键

什么是复合主键

mysql的联合主键与复合主键区别