聚簇索引(Clustered Index)vs 非聚簇索引(Non-clustered Index)

好的,聚簇索引(Clustered Index)和非聚簇索引(Non-clustered Index)是关系型数据库中两种核心的索引结构,最根本的区别在于索引的叶子节点存储的内容。这会带来一系列性能和结构上的差异。

以下是它们的核心区别:

特性聚簇索引 (Clustered Index)非聚簇索引 (Non-clustered Index)
叶子节点存储内容实际的数据行本身。找到索引就找到了数据。指向数据行位置的指针(或书签)。找到索引后,需要通过这个指针去查找实际的数据行(这个过程称为“回表”)。
数据物理排序数据行在磁盘上的物理存储顺序与索引的逻辑顺序完全一致(或非常接近)。表数据本身就是索引结构的一部分。不影响数据行的物理存储顺序。索引是独立于数据行的额外结构。数据行可以以堆(Heap)或其他形式存储。
数量限制每张表只能有一个聚簇索引(因为数据行本身只能以一种物理顺序存储)。每张表可以有多个非聚簇索引(可以创建在不同列上以满足不同查询需求)。
查询速度 (主键/范围查询)非常快。特别是基于索引列的范围查询或排序,因为数据物理连续,减少I/O。相对较慢。如果查询需要访问非索引列,必须进行额外的“回表”操作,增加I/O。
查询速度 (覆盖查询)如果查询的列都在索引中,速度很快。但聚簇索引本身包含所有列。如果索引包含查询所需的所有列(覆盖索引),速度可以非常快,甚至超过聚簇索引(因为索引更小),无需回表。
插入速度相对较慢。插入新行时,数据库需要找到正确的物理位置插入,可能导致页分裂,影响性能。相对较快。只需在索引结构中插入指向新数据行位置的指针。
更新索引列值代价很高。更新聚簇索引键列的值时,可能导致该行数据移动到新的物理位置(因为物理顺序变了),所有非聚簇索引都需要更新指针。代价较低。如果更新的是非索引列,非聚簇索引不受影响。如果更新的是索引列,只需更新该索引结构本身。
空间占用更大。索引结构包含了完整的数据行。更小。只存储索引键列的值和指向数据行的指针。
典型例子在 MySQL InnoDB 中,主键 (PRIMARY KEY) 默认就是聚簇索引。如果没有主键,InnoDB 会创建一个隐藏的聚簇索引。在 MySQL InnoDB 中,除了主键索引以外的索引(如 UNIQUE INDEX, INDEX)都是非聚簇索引(二级索引)。
类比像一本按拼音排序的字典。拼音顺序(索引)直接决定了字(数据)在书中的物理位置。查找拼音就找到了字。像一本按部首查字的字典。部首目录(索引)告诉你字在哪个页码(指针),你需要翻到那个页码(回表)才能看到字的具体解释(数据)。

关键点详解:

  1. 叶子节点存储内容(核心区别):

    • 聚簇索引: 叶子节点就是数据页。索引键值 + 该行所有其他列的数据都存储在这里。
    • 非聚簇索引: 叶子节点只包含索引键值和一个指向实际数据行物理位置的指针(在 InnoDB 中,这个指针通常是主键值;在 SQL Server/使用堆表的数据库中是 RID (Row ID))。
  2. 数据物理排序:

    • 聚簇索引: 决定了表中数据的物理存储顺序。数据行按聚簇索引键的顺序存储在磁盘上(或尽可能接近)。这是为什么一张表只能有一个聚簇索引的根本原因。
    • 非聚簇索引: 是一个完全独立的结构。它有自己的排序顺序(按索引键排序),但这个顺序与数据行在磁盘上的物理顺序无关
  3. 二级索引(非聚簇索引)与聚簇索引的协作:

    • 当通过非聚簇索引查找数据时:
      1. 数据库引擎首先在非聚簇索引中找到目标行的索引条目。
      2. 从该索引条目中取出指向实际数据行的指针(在 InnoDB 中是主键值)。
      3. 使用这个指针(主键值)回到聚簇索引中进行查找
      4. 在聚簇索引中找到对应的叶子节点(即数据页),读取完整的行数据。
    • 这个“回到聚簇索引查找”的过程就是回表(Bookmark Lookup 或 Key Lookup)。它是额外的开销。如果非聚簇索引本身包含了查询需要的所有列(称为“覆盖索引”),就可以避免回表,大大提高查询速度。
  4. 性能影响:

    • 聚簇索引优势:
      • 基于聚簇索引键的范围查询(BETWEEN, >, <, ORDER BY极快,因为需要的数据在物理上是连续的,I/O 效率高。
      • 按主键(通常是聚簇索引)精确查找极快
    • 聚簇索引劣势:
      • 插入速度可能变慢(需要找到正确位置插入,可能导致页分裂)。
      • 更新聚簇索引键列的代价非常高(数据行可能移动,所有非聚簇索引都需要更新指针)。
    • 非聚簇索引优势:
      • 提供额外的访问路径,加速基于其他列的查询。
      • 创建覆盖索引可以避免回表,极大提升特定查询速度。
      • 插入通常比聚簇索引快(只需追加到索引)。
    • 非聚簇索引劣势:
      • 可能导致回表操作,增加 I/O,降低查询速度(特别是需要返回多列数据时)。
      • 需要额外的存储空间。

总结:

  • 聚簇索引就是表数据本身,它决定了数据的物理顺序。它是表的主干结构。查找快(尤其范围查询),但更新键值或插入可能导致代价高的维护操作。一张表只能有一个
  • 非聚簇索引是一个独立的查找结构,它存储索引键和指向数据行的指针。它提供了额外的快速访问路径。一张表可以有多个。查询时可能需要额外的“回表”步骤,但如果设计成“覆盖索引”,性能可以非常好。

选择建议:

  1. 主键通常是聚簇索引的最佳选择(在 InnoDB 中默认如此),因为它通常是唯一的、递增的(减少页分裂),并且是许多查询的访问点。
  2. 经常出现在 WHERE 子句、JOIN 条件、ORDER BYGROUP BY 中的列创建非聚簇索引。
  3. 考虑创建覆盖索引来避免回表,提升关键查询性能。
  4. 避免在频繁更新的列上创建过多索引,因为维护索引也有开销。
  5. 了解你所使用的数据库引擎的具体实现细节(如 InnoDB 强制使用聚簇索引,MyISAM 只使用非聚簇索引等)。

理解聚簇索引和非聚簇索引的区别对于设计高效的数据库模式、索引策略以及优化查询性能至关重要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值