主键与聚集索引的关系


91

可以 TABLE有没有聚集索引的主键吗?

并且可以 TABLE没有主键的情况下拥有聚集索引吗?

谁能简要告诉我主键和聚簇索引之间的关系?

Answers:


102

主键是逻辑的概念-它是表中一行的唯一标识符。因此,它具有许多属性-不能为null,并且必须唯一。当然,由于您很可能会通过其唯一标识符来搜索很多记录,因此最好在主键上有一个索引。

聚簇索引是一个物理概念-它是影响记录在磁盘上存储顺序的索引。这使它成为访问数据时非常快的索引,但是如果您的主键不是序列号,它可能会减慢写入速度。

是的,您可以拥有一个不带聚集索引的主键-有时您可能想要(例如,当主键是联接表上的外键组合,并且您不想造成磁盘改组开销时)写作时)。

是的,您可以在不是主键的列上创建聚簇索引。


1
你好 主题很旧,但也许有人可以回答我的问题。如果将列声明为NOT NULL UNIQUE CLUSTERED INDEX,将其设置为PRIMARY KEY会对性能产生任何实际变化吗?
jesse

这是一个有趣的问题。我认为不会,因为它必须以任何一种方式执行所有相同的检查。
乔纳森·艾伦

辉煌的答案。
NikosV

但是大多数情况下,具有聚簇索引的主键列将非常有用,因为它可以大大简化范围查找。
hunter_tech

33

表可以具有未集群的主键,并且集群表不需要主键。因此,这两个问题的答案都是肯定的。

聚集索引将所有列存储在叶级别。这意味着聚集索引包含表中的所有数据。没有聚集索引的表称为堆。

主键是默认情况下聚集的唯一索引。默认情况下,这意味着当您创建主键时,如果表尚未群集,则主键将被创建为群集的唯一索引。除非您明确指定该nonclustered选项。

一个示例,其中t1具有非集群主键,并且t2没有集群但具有主键:

create table t1 (id int not null, col1 int);
alter table t1 add constraint PK_T1 primary key nonclustered (id);
create clustered index IX_T1_COL1 on t1 (col1);

create table t2 (id int not null, col1 int);
alter table t2 add constraint PK_T2 primary key nonclustered (id);

SQL Fiddle中的示例。


18

首先,看一下索引组织表和聚簇索引。实际上,我建议您阅读整个使用索引卢克!网站从一开始到您到达集群主题为止,以真正了解正在发生的事情。

现在,您的问题...


TABLE是否可以具有没有聚簇索引的主键?

是的,在声明主键来创建基于堆的表时,请使用NONCLUSTERED关键字。例如:

CREATE TABLE YOUR_TABLE (
    YOUR_PK int PRIMARY KEY NONCLUSTERED
    -- Other fields...
);

这很不幸,因为尽管在许多情况下基于堆的表实际上会更好(如链接文章中所述),但许多人似乎只接受默认值(即CLUSTERED)。


和表可以具有不带主键的聚簇索引吗?

与某些其他DBMS不同,MS SQL Server将使您拥有与主键不同的聚簇索引,甚至完全没有主键。

下面的示例创建一个与PK分开的聚簇索引,该聚簇索引在其顶部具有UNIQUE约束,这在大多数情况下可能是您想要的:

CREATE TABLE YOUR_TABLE (
    YOUR_PK int PRIMARY KEY,
    YOUR_CLUSTERED_KEY int NOT NULL UNIQUE CLUSTERED
    -- Other fields...
);

如果选择非唯一的聚簇索引(使用CREATE CLUSTERED INDEX ...),则MS SQL Server将通过向其添加隐藏字段来自动使其唯一。

请注意,群集的优势对于范围扫描最为明显。如果您使用的聚簇索引与客户端应用程序进行的范围扫描不“对齐”(例如,当过度依赖上述隐藏列或使用代理键进行聚簇时),那么您几乎可以达到集群的目的。


有人可以简单地告诉我主键和聚簇索引的关系吗?

在MS SQL Server下,默认情况下,主键也是群集。您可以更改默认值,如上所述。


4

MSDN使用聚簇索引得出的答案

TABLE是否可以具有没有聚簇索引的主键?-是的

TABLE是否可以具有不带主键的聚集索引?-是的

主键是一个约束,以确保唯一性的值,使得一个行总是可以特别地由键标识。

索引被自动分配给主键(如行通常“抬头”可以通过主键)。

非聚集索引是行的逻辑顺序,由它的列的一个(或多个)。可以有效地将其视为表的另一个“副本”,按索引所经过的任何列排序。

一个聚集索引是当实际的表在物理上按特定的列进行排序。一个表并不总是具有聚簇索引(即,虽然它由某物物理排序,但该东西可能是未定义的)。一个表不能有多个聚簇索引,尽管它可以有一个复合聚簇索引(即该表在物理上按姓,名,DOB排序)。

PK通常(但不总是)是聚集索引。


在SQL Server中,默认情况下将对主键进行群集化-除非您明确要求不要这样做。但这只是默认设置,而不是必需条件。
marc_s

一个表可以有没有任何索引的主键吗?因为,当我说一列是主键时,默认情况下会创建聚簇索引。删除索引时,表是否不再包含主键?
veljasije 2013年

1

出于价值考虑,在MS SQL Server中,主键中的所有列都必须定义为NOT Null,而创建唯一的聚集索引不需要这样做。虽然不确定其他数据库系统。


这是在答案下标记为正确答案的更多评论。
Jan Doggen

1
欢迎使用-我给您+1,因为我发现您尚无要添加评论的名声。(到那儿去做:)
逆向工程师

0

它可能与该问题的答案无关,但是关于主键和聚集索引的一些重要方面是->

如果存在带有聚簇索引的主键(默认情况下为聚簇索引,但是我们可以更改它),那么我们将无法为该表再创建一个聚簇索引。但是,如果还没有主键集,并且有聚簇索引,那么我们就不能用聚簇索引创建主键。

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.