何时应该使用主键或索引?

60

我应该何时使用主键或索引?

它们有什么区别,哪一个是最好的?

6个回答

40

基本上,主键在实现层面上是一种特殊类型的索引。具体而言:

  • 一个表只能有一个主键,在极少数情况下,每个表都应该有一个。
  • 主键隐含了UNIQUE属性 - 由于其目的是唯一标识行,不能有多行使用相同的主键。
  • 主键永远不可能为空,因此它所包含的行必须为非空。

一个表可以拥有多个索引,并且索引不一定是UNIQUE的。索引存在的两个原因:

  • 强制实施唯一约束(当您声明一个列为 UNIQUE 时,这些可以隐式创建)
  • 提高性能。在 WHERE 子句中进行相等或“大于/小于”比较以及 JOIN 在具有索引的列上更快。但请注意,每个索引会降低更新/插入/删除的性能,因此您只应在需要时使用它们。

14
主键是一个约束条件不是索引。索引可以与主键关联,但不是必需的。除非使用SQL Server,否则索引不能确保唯一性。 - OMG Ponies
1
@OMG:从技术上讲,主键约束(就像唯一约束一样)总是通过索引实现的。如果声明了索引,则索引确保唯一性。 - Michael Borgwardt
6
MySQL和PostgreSQL都有CREATE UNIQUE INDEX语法。而Postgres手册中表示:“当为表定义唯一约束或主键时,PostgreSQL会自动创建唯一索引。(...) 索引是实施约束的机制。”链接:http://www.postgresql.org/docs/8.0/interactive/indexes-unique.html -- 我认为我们的分歧源于我将索引概念视为实现细节,而您则将索引视为SQL DDL的抽象部分。 - Michael Borgwardt
1
@David:斯坦福大学的某位人士对Oracle持不同意见:“Oracle会自动为每个UNIQUE或PRIMARY KEY声明创建一个索引。请注意,您无法删除UNIQUE和PRIMARY KEY属性的索引。” http://infolab.stanford.edu/~ullman/fcdb/oracle/or-nonstandard.html#indexes - 是的,键和索引在概念上是不同的,但在实现层面上,索引将被用于有效地强制执行键或唯一约束。 - Michael Borgwardt
SQLite中的主键列允许多次插入“Null”作为主键,原因是:null = null > false。 - Eminem
显示剩余5条评论

26

区别

表格只能有一个主键,但可以有多个索引

主键是唯一的,而索引不一定是唯一的。因此,主键值可以用来识别表格中的记录,而索引值则不一定如此。

通常情况下,主键会自动创建索引 - 如果您创建了主键,则无需在相同的列上创建索引。

何时使用何种方式

每个表都应该有一个主键。定义一个主键,可以保证每个记录都具有唯一性。

如果您经常在连接或where语句中使用其他列,索引可以加快查询速度。 然而,创建和删除记录时索引会增加一些负担,如果插入和删除大量记录时需要注意这一点。

哪种方式是最好的?

其实没有最好的方法-每个方法都有其特定目的。并且您并非真正可以选择使用哪种方法。

我建议您首先问自己表格的主键是什么,然后定义它。

通过个人经验或者如果出现性能问题,添加索引。要衡量差异,如果您使用SQL Server,请学习如何读取执行计划。


7
这可能会有所帮助:回归基础:主键和唯一索引的区别 两者之间的区别如下:
  1. 组成表的主键列不能为空,因为根据定义,主键不能为NULL,因为它有助于在表中唯一标识记录。组成唯一索引的列可以为空。值得一提的是,不同的RDBMS对此的处理方式不同->虽然SQL Server和DB2不允许在唯一索引列中有多个NULL值,但Oracle允许多个NULL值。这是设计/开发/移植跨RDBMS应用程序时要注意的事情之一。
  2. 一张表上只能定义一个主键,而你可以在一张表上定义多个唯一索引(如果需要)。
  3. 此外,在SQL Server的情况下,如果您选择默认选项,则创建主键作为聚集索引,而唯一索引(约束)则创建为非聚集索引。这仅是默认行为,如果需要,可以在创建时更改。

7
键和索引是实现不同目的的两个概念。键是一个逻辑约束,要求元组是唯一的。索引是数据库的性能优化功能,因此是数据库的物理特征而不是逻辑特征。
这两者之间的区别有时会变得模糊,因为经常使用类似或相同的语法来指定约束和索引。许多DBMS在创建关键约束时默认创建索引。键和索引之间的潜在混淆是不幸的,因为分离逻辑和物理关注是数据管理的一个非常重要的方面。
至于“主”键。它们不是“特殊”的键类型。主键只是表中任何一个候选键。在大多数SQL DBMS中,至少有两种方法可以创建候选键,即使用PRIMARY KEY约束或在NOT NULL列上使用UNIQUE约束。每个SQL表都有一个主键约束是一个广泛接受的传统。使用主键约束是常识和完全合理的事情,但通常没有实际或逻辑差异,因为大多数DBMS将所有键视为相等的。当然,每个表都应强制执行至少一个候选键,但这些键是由PRIMARY KEY还是UNIQUE约束强制执行并不重要。原则上,候选键是重要的,而不是“主”键。

6
主键是唯一的,它定义了每个单独行的标识。在表中始终需要一个主键,因为这是唯一的识别行的方法。
索引基本上是一个针对字段或一组字段的字典。当您请求数据库查找某个字段等于某个特定值的记录时,它可以查找字典(索引)以找到正确的行。这非常快,因为就像字典一样,索引中的条目已排序,从而允许进行二进制搜索。如果没有索引,则数据库必须读取表中的每一行并检查该值。
通常要向需要过滤的每个列添加索引。如果您搜索特定组合的列,则可以创建包含所有这些列的单个索引。如果这样做,相同的索引可用于搜索索引列表中任何前缀的列。简单地说(有点不准确),字典包含按指定顺序使用的列中使用的值的串联条目,因此数据库可以查找以特定值开头的条目,并仍然使用高效的二进制搜索。
例如,如果您在列(A,B,C)上有一个索引,则即使只过滤A,也可以使用此索引,因为那是索引中的第一列。类似地,如果您过滤A和B,则可以使用它。但是,如果您只过滤B或C,则无法使用它,因为它们不是列列表中的前缀 - 您需要另一个索引来容纳它。
主键也作为索引,因此您无需添加覆盖与主键相同的列的索引。

3
在表中,始终需要一个主键,因为这是唯一识别行的方法。但不是这样的,一个唯一约束,可以跨越多个列(这些列都具有NOT NULL约束),也可以识别一行。 - Hibou57
@Hibou57 - 我同意。我已经想了好几年了。PK是否只是一种快捷实现特定类型索引的方法?唯一、所有列非空、不包含任何其他列,不基于条件?在我看来,我创建的每个PK都可以被实现为等效的索引。 - Yossi G.

1
每个表都应该有一个主键。
通过明智选择索引,可以加快许多类型的查询。最好的索引可能是主键。我的观点是,查询是使用PK作为其索引的主要因素。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接