可以TABLE
有一个没有聚集索引的主键吗?
并且可以在TABLE
没有主键的情况下拥有聚集索引吗?
谁能简单地告诉我主键和聚集索引之间的关系?
可以TABLE
有一个没有聚集索引的主键吗?
并且可以在TABLE
没有主键的情况下拥有聚集索引吗?
谁能简单地告诉我主键和聚集索引之间的关系?
主键是一个逻辑概念——它是表中行的唯一标识符。因此,它有一堆属性——它可能不为空,而且它必须是唯一的。当然,由于您可能经常通过其唯一标识符搜索记录,因此最好在主键上建立一个索引。
聚集索引是一个物理概念——它是一个影响记录在磁盘上存储顺序的索引。这使得它在访问数据时成为一个非常快速的索引,但如果您的主键不是序列号,它可能会减慢写入速度。
是的,您可以拥有没有聚集索引的主键 - 有时,您可能想要(例如,当您的主键是连接表上的外键组合时,并且您不想招致磁盘洗牌开销写的时候)。
是的,您可以在不是主键的列上创建聚集索引。
一个表可以有一个非聚集的主键,而一个聚集的表不需要主键。所以这两个问题的答案都是肯定的。
聚集索引在叶级别存储所有列。这意味着聚集索引包含表中的所有数据。没有聚集索引的表称为堆。
主键是默认聚集的唯一索引。默认情况下,当你创建主键时,如果表还没有聚集,主键将被创建为聚集唯一索引。除非您明确指定该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);
首先,看一下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 下,主键默认也是集群的。如上所述,您可以更改该默认值。
从MSDN Using Clustered Indexes得到的答案
TABLE 可以有没有聚集索引的主键吗?- 是的。
TABLE 可以有没有主键的聚集索引吗?- 是的。
主键是确保值的唯一性的约束,因此可以始终由该键专门标识 行。
索引会自动分配给主键(因为行通常通过其主键“查找”)。
非聚集索引是行的一个(或多个)列的逻辑排序。将其视为有效的表的另一个“副本”,按索引所在的任何列排序。
聚集索引是指实际表按特定列进行物理排序。一个表并不总是有一个聚集索引(即,虽然它会被某些东西物理排序,但那个东西可能是未定义的)。一个表不能有多个聚簇索引,尽管它可以有一个复合聚簇索引(即,该表按姓氏、名字、出生日期等物理排序)。
PK 通常(但不总是)是聚集索引。
值得一提的是,在 MS SQL Server 中,主键中的所有列都必须定义为 NOT Null,而创建唯一聚集索引则不需要这样做。不过不确定其他数据库系统。
它可能与这个问题的答案无关,但主键和聚集索引的一些重要方面是 ->
如果有一个带有聚集索引的主键(默认情况下是聚集索引,但是我们可以更改它),那么我们不能为该表创建一个更多聚集索引。但是如果还没有设置主键,并且有聚集索引,那么我们就不能用聚集索引创建主键。