sql主键和索引


106

假设我在数据库中有一个ID行(int)设置为主键。如果我经常查询ID,是否还需要为其编制索引?还是作为主键意味着它已经被索引了?

我问的原因是因为在MS SQL Server中,我可以在此ID上创建索引,正如我所说的,这是我的主键。

编辑:另一个问题-额外索引主键会不会有任何危害?

Answers:


73

没错,SQL Server允许您在同一字段上创建重复的索引令人困惑。但是您可以创建另一个的事实并不表示PK索引还不存在。

附加索引没有好处,但是唯一的危害(很小)是附加的文件大小和行创建开销。


39
未使用索引的损坏确实是非常有害的。一方面,索引消耗了存储空间。另一方面,它减慢了写入和更新的速度。始终删除将不使用的索引。
Pacerier

50

正如其他人已经说过的那样,主键会自动索引。

仅在需要优化使用主键和某些其他特定列的查询时,才需要在主键列上创建更多索引。通过在主键列上创建另一个索引,并在其中包含其他一些列,可以实现查询的所需优化。

例如,您有一个包含许多列的表,但是仅查询ID,Name和Address列。以ID为主要键,我们可以创建以下基于ID的索引,但其中包括Name和Address列。

CREATE NONCLUSTERED INDEX MyIndex
ON MyTable(ID)
INCLUDE (Name, Address)

因此,当您使用此查询时:

SELECT ID, Name, Address FROM MyTable WHERE ID > 1000

SQL Server将仅使用您创建的索引为您提供结果,并且不会从实际表中读取任何内容。


28

注意:此答案适用于大型企业级开发。

这是一个RDBMS问题,而不仅仅是SQL Server,其行为可能非常有趣。一方面,虽然通常会自动(唯一)索引主键,但这不是绝对的。 有时候,必须不要对主键进行唯一索引。

在大多数RDBMS中,如果主索引尚不存在,则会自动在主键上创建唯一索引。。因此,可以在将其声明为主键之前在主键列上创建自己的索引,然后在应用主键声明时数据库引擎将使用该索引(如果可接受)。通常,您可以创建主键并允许创建其默认唯一索引,然后在该列上创建自己的备用索引,然后删除默认索引。

现在有趣的部分是什么时候不想要唯一的主键索引?当您的表获取足够的数据(行)以致于维护索引的成本太高时,您将不希望也不能容忍一个。这取决于硬件,RDBMS引擎,表和数据库的特征以及系统负载。但是,一旦表达到几百万行,它通常就会开始显现。

根本问题是每次插入一行或更新主键列都会导致索引扫描以确保唯一性。随着表的增长,唯一索引扫描(或等效于任何RDBMS的等效索引扫描)变得越来越昂贵,直到它支配了表的性能。

我用多达20亿行的表,8 TB的存储量和每天四千万行的插入量来处理这个问题很多次。我的任务是重新设计所涉及的系统,其中实际上包括将唯一主键索引删除作为第一步。的确,在我们甚至接近重新设计之前,降低该索引对于生产来说只是为了从中断中恢复是必要的。重新设计包括寻找其他方法来确保主键的唯一性并提供对数据的快速访问。


如果密钥是int或bigint自动递增密钥怎么办?SQL Server是否足够聪明,在这种情况下不执行唯一索引扫描?
quillbreaker,

1
@quillbreaker:IDENTITY不保证字段唯一。毕竟,如果用户使用,则用户可以插入重复的值IDENTITY_INSERT

我知道这是一个古老的话题,但我不了解对一个索引进行唯一性扫描将如何对系统造成如此大的负担。B +树扫描应为O(log n)* v,其中v限制了索引碎片,不完美的树平衡等开销。因此,20亿行将是2,000,000,000(约31个寻道)次数的对数基数2,例如, 2或3甚至10个。每天40M插入速度约为462 / sec,每个插入速度约为100 IO ... 我懂了。而这是在广泛使用SSD之前。
Charles Burns

除非您放弃唯一性约束,否则检查每一行的唯一性的开销不会更大吗?
Max Candocia


9

这是MSDN的文章

当您为表指定PRIMARY KEY约束时,数据库引擎将通过为主键列创建唯一索引来强制数据唯一性。当在查询中使用主键时,该索引还允许快速访问数据。因此,选择的主键必须遵循创建唯一索引的规则。



3

声明PRIMARY KEYUNIQUE约束会导致SQL Server自动创建索引。

可以在不匹配约束的情况下创建唯一索引,但是没有唯一索引就不能存在约束(主键或唯一)。

从这里开始,约束的创建将:

  • 导致创建具有相同名称的索引
  • 拒绝删除创建的索引,因为没有约束就不存在约束

同时删除约束将删除关联的索引。

因此,a PRIMARY KEY或之间是否存在实际差异UNIQUE INDEX

  • NULL不允许在值中使用PRIMARY KEY,但允许在UNIQUE索引中使用;就像在集合运算符(UNION,EXCEPT,INTERSECT)中一样,在这里NULL = NULL这意味着您只能拥有一个值,因为两个值NULL是彼此重复的;
  • PRIMARY KEY每个表只能存在一个,而可以创建999个唯一索引
  • PRIMARY KEY创建约束时,除非表上已经存在聚集索引或NONCLUSTERED在其定义中使用了约束,否则它将作为聚集创建。UNIQUE创建索引时,NONCLUSTERED除非没有特定的索引并且索引CLUSTERED已经不存在,否则将创建索引;


1

在SQL Server中,通常,主键是自动索引的。的确如此,但是不能保证更快的查询速度。当只有1个字段作为主键时,主键将为您提供出色的性能。但是,当有多个字段作为主键时,则索引基于这些字段。

例如:字段A,B,C是主键,因此,当您基于WHERE CLAUSE中的那三个字段进行查询时,性能很好;但是,当您要查询WHERE CLAUSE中的Only C字段时,您将不会获得良好的性能。因此,为了使性能正常运行,您将需要手动索引C字段。

大多数情况下,只有达到100万条以上的记录,您才会看到该问题。


0

我有一个庞大的数据库,没有(单独的)索引。

每当我通过主键查询结果时,出于所有重要目的,结果都是即时的。


那是因为PK是聚集索引,请查看您的查询计划
SQLMenace

0

主键自动索引

您可以根据使用情况使用pk创建其他索引

  • 如果您经常通过zip_code和id选择索引zip_code,id,则可能会有所帮助
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.