104

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

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

谁能简单地告诉我主键和聚集索引之间的关系?

4

6 回答 6

119

主键是一个逻辑概念——它是表中行的唯一标识符。因此,它有一堆属性——它可能不为空,而且它必须是唯一的。当然,由于您可能经常通过其唯一标识符搜索记录,因此最好在主键上建立一个索引。

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

是的,您可以拥有没有聚集索引的主键 - 有时,您可能想要(例如,当您的主键是连接表上的外键组合时,并且您不想招致磁盘洗牌开销写的时候)。

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

于 2013-02-24T12:54:18.247 回答
38

一个表可以有一个非聚集的主键,而一个聚集的表不需要主键。所以这两个问题的答案都是肯定的。

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

主键是默认聚集的唯一索引。默认情况下,当你创建主键时,如果表还没有聚集,主键将被创建为聚集唯一索引。除非您明确指定该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 的示例。

于 2013-02-24T12:53:29.587 回答
22

首先,看一下Index-Organized Tables 和 Clustered Indexes。实际上,我建议阅读整个使用索引卢克!从一开始,直到您到达集群主题才能真正了解正在发生的事情。

现在,对于你的问题...


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 下,主键默认也是集群的。如上所述,您可以更改该默认值。

于 2013-02-24T16:10:50.320 回答
4

MSDN Using Clustered Indexes得到的答案

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

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

主键是确保值的唯一性的约束,因此可以始终由该键专门标识 行

索引会自动分配给主键(因为行通常通过其主键“查找”)。

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

聚集索引是指实际按特定列进行物理排序。一个表并不总是有一个聚集索引(即,虽然它会被某些东西物理排序,但那个东西可能是未定义的)。一个表不能有多个聚簇索引,尽管它可以有一个复合聚簇索引(即,该表按姓氏、名字、出生日期等物理排序)。

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

于 2013-02-24T12:58:27.857 回答
1

值得一提的是,在 MS SQL Server 中,主键中的所有列都必须定义为 NOT Null,而创建唯一聚集索引则不需要这样做。不过不确定其他数据库系统。

于 2015-02-23T15:39:32.237 回答
0

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

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

于 2014-01-09T19:05:40.317 回答