【发布时间】:2013-02-24 12:49:06
【问题描述】:
TABLE 可以有一个没有聚集索引的主键吗?
TABLE 可以在没有主键的情况下拥有聚集索引吗?
谁能简单介绍一下主键和聚集索引的关系?
【问题讨论】:
标签: sql sql-server database database-design
TABLE 可以有一个没有聚集索引的主键吗?
TABLE 可以在没有主键的情况下拥有聚集索引吗?
谁能简单介绍一下主键和聚集索引的关系?
【问题讨论】:
标签: sql sql-server database database-design
主键是一个逻辑 概念——它是表中行的唯一标识符。因此,它有一堆属性——它可能不为空,而且它必须是唯一的。当然,由于您可能经常通过其唯一标识符搜索记录,因此最好在主键上建立索引。
聚集索引是一个物理概念——它是一个影响记录在磁盘上存储顺序的索引。这使它在访问数据时成为一个非常快速的索引,但如果您的主键不是序列号,它可能会减慢写入速度。
是的,您可以有一个没有聚集索引的主键 - 有时,您可能想要(例如,当您的主键是连接表上的外键组合时,您不想招致写入时的磁盘洗牌开销)。
是的,您可以在不是主键的列上创建聚集索引。
【讨论】:
一个表可以有一个非聚簇的主键,一个聚簇的表不需要主键。所以这两个问题的答案都是肯定的。
聚集索引在叶级存储所有列。这意味着聚集索引包含表中的所有数据。没有聚集索引的表称为堆。
主键是默认聚集的唯一索引。默认情况下,当您创建主键时,如果该表尚未聚集,则主键将创建为聚集唯一索引。除非您明确指定 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 and Clustered Indexes。实际上,我建议您从头开始阅读整个 Use the Index Luke! 站点,直到您到达集群主题才能真正了解发生了什么。
现在,回答您的问题...
一个 TABLE 可以有没有聚集索引的主键吗?
是的,在声明主键以创建基于堆的表时,请使用 NONCLUSTERED 关键字。例如:
CREATE TABLE YOUR_TABLE (
YOUR_PK int PRIMARY KEY NONCLUSTERED
-- Other fields...
);
这很不幸,因为很多人似乎只是接受默认值(即 CLUSTERED),尽管在许多情况下基于堆的表实际上会更好(如链接文章中所述)。
TABLE 可以有没有主键的聚集索引吗?
与其他一些 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 会自动通过添加一个隐藏字段使其唯一。
请注意,集群的好处在范围扫描中最为明显。如果您使用的集群索引与客户端应用程序完成的范围扫描不“对齐”(例如过度依赖上述隐藏列或在surrogate key 上进行集群时),那么您很漂亮大大违背了集群的目的。
谁能简单介绍一下主键和聚集索引的关系?
在 MS SQL Server 下,主键默认也是集群的。如上所述,您可以更改该默认值。
【讨论】:
答案来自MSDN Using Clustered Indexes
一个 TABLE 可以有没有聚集索引的主键吗? - 是的。
TABLE 可以有没有主键的聚集索引吗? - 可以。
Primary Key 是一个约束,它确保值的唯一性,以便始终可以通过该键专门标识行。
索引会自动分配给主键(因为行通常通过主键“查找”)。
非聚集索引是行的一个(或多个)列的逻辑排序。可以将其视为有效的表的另一个“副本”,按索引所在的列排序。
聚集索引是指实际表按特定列物理排序。一个表并不总是有一个聚集索引(即,虽然它会按something 进行物理排序,但那个东西可能是undefined)。一个表不能有多个聚簇索引,尽管它可以有一个复合聚簇索引(即,该表按 Surname、Firstname、DOB 等物理排序)。
PK 通常(但不总是)是聚集索引。
【讨论】:
不管怎样,在 MS SQL Server 中,主键中的所有列都必须定义为 NOT Null,而创建唯一聚集索引则不需要这样做。不过不确定其他数据库系统。
【讨论】:
它可能与这个问题的答案无关,但关于主键和聚集索引的一些重要方面是 ->
如果有一个带有聚集索引的主键(默认情况下是聚集索引,但是我们可以更改它),那么我们不能为该表创建一个更多聚集索引。 但是如果还没有设置主键,并且有聚集索引,那么我们就不能用聚集索引创建主键。
【讨论】: