【问题标题】:Relationship of Primary Key and Clustered Index主键与聚集索引的关系
【发布时间】:2013-02-24 12:49:06
【问题描述】:

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

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

谁能简单介绍一下主键和聚集索引的关系?

【问题讨论】:

    标签: sql sql-server database database-design


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 嗨。话题很老,但也许有人可以回答我的问题。如果将列声明为 NOT NULL UNIQUE CLUSTERED INDEX,将其设为 PRIMARY KEY 是否会对性能或其他任何内容进行任何实际更改?
    • 这是一个有趣的问题。我认为不会,因为它必须以任何一种方式执行所有相同的检查。
    • 出色的答案。
    • 但大多数情况下,带有聚集索引的主键列会很有用,因为它大大简化了范围搜索。
    【解决方案2】:

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

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

    主键是默认聚集的唯一索引。默认情况下,当您创建主键时,如果该表尚未聚集,则主键将创建为聚集唯一索引。除非您明确指定 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);
    

    Example at SQL Fiddle.

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        答案来自MSDN Using Clustered Indexes

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

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

        Primary Key 是一个约束,它确保值的唯一性,以便始终可以通过该键专门标识行。

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

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

        聚集索引是指实际表按特定列物理排序。一个表并不总是有一个聚集索引(即,虽然它会按something 进行物理排序,但那个东西可能是undefined)。一个表不能有多个聚簇索引,尽管它可以有一个复合聚簇索引(即,该表按 Surname、Firstname、DOB 等物理排序)。

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

        【讨论】:

        • 在 SQL Server 中,默认情况下主键会被集群化——除非你明确告诉它不要集群化。但这只是一个默认值 - 不是要求。
        • 表可以有主键而没有索引吗?因为,当我说一列是主键时,默认情况下会创建聚集索引。删除索引时,表不再包含主键?
        【解决方案5】:

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

        【讨论】:

        • 这更多的是在标记为正确的答案下的评论。
        • 欢迎 - 我给你一个 +1,因为我看到你还没有添加 cmets 的声誉。 (去过那里,做到了:)
        【解决方案6】:

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

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

        【讨论】:

          猜你喜欢
          • 2018-12-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-03
          • 1970-01-01
          • 2021-09-07
          • 1970-01-01
          • 2017-08-20
          相关资源
          最近更新 更多