使用过MySQL数据库或其他关系型数据库的开发者应该都对索引有所了解。在MySQL中,索引是一种用于优化查询性能的重要机制,而常见的索引类型包括聚集索引(Clustered Index,也称为聚类索引或簇集索引)和非聚集索引(Non-Clustered Index,也称为非聚类索引或非簇集索引)。

这两个概念是学习和深入掌握MySQL数据库绕不开的基础理论知识,理解它们对数据存储和查询优化有着重要意义。本文将带大家系统地复习一下MySQL中的这两类索引。

索引的分类

索引在数据库中的作用类似于书籍的目录,也类似于查找汉语字典时的部首目录或拼音目录。它们的核心目的相同,都是为了提高数据查找的效率。通过索引,可以避免对整张表的数据进行全表扫描,快速定位到所需数据,从而显著提升查询的速度。

以MySQL的索引实现为例,从其数据的物理存储逻辑索引的关系角度来看,可以将索引分为两类:聚集索引(Clustered Index)和非聚集索引(Non-Clustered Index)。这些索引的特性和使用方式在MySQL数据库设计中扮演着非常重要的角色。

聚集索引(Clustered Index)

聚集索引是一种独特的索引类型,它定义了数据库表中数据的物理存储顺序与索引键值的逻辑顺序是一致的。由于数据的物理存储顺序对于表是固定的,因此一个表只能有一个聚集索引。如果一个索引不是聚集索引,那么表中的行数据的物理存储顺序与索引顺序不匹配。ß

与非聚集索引相比,聚集索引通常具有更快的检索速度,原因是聚集索引的叶子节点存储了真实的数据行(而非指向数据的页索引)。这使得通过聚集索引可以直接获取数据,而无需额外的查找跳转。

聚集索引的特性

  • 物理存储顺序 聚集索引确定了数据在磁盘上的物理存储顺序,类似于一本字典按字母顺序排列。字母作为索引键,字母下的多个单词代表表中的数据行。 比如,对于一个按用户ID排序的用户表,表中的数据行会按照用户ID的顺序存储。而叶子节点存储了真实数据行,因此通过聚集索引可以直接访问表中的数据。
  • 自动创建的主键索引 通常,当为某张表定义了主键时,数据库会默认将主键列作为聚集索引,并根据主键的值对数据进行排序和存储。

数据访问方式

在查询时,聚集索引具有显著的性能优势。由于表中的数据物理存储顺序与索引键值顺序一致,如果查询条件基于聚集索引列(例如主键),数据库可以直接通过索引定位到磁盘上的数据行,而无需进行全表扫描。

示例:

  • 假设一个订单表的订单ID是聚集索引,当查询某个订单ID对应的订单信息时,数据库会直接根据订单ID的索引值快速定位到磁盘上的数据行,从而快速返回查询结果。
  • 对于范围查询(如 “SELECT * FROM orders WHERE order_id BETWEEN 1000 AND 2000″),聚集索引因为数据已经按照索引顺序存储,查询性能会非常优越。

性能开销

聚集索引的结构带来了一些性能方面的权衡:

  • 插入与更新开销 由于聚集索引决定了数据的物理存储顺序,插入或更新数据时可能会导致数据行的移动或重新排序。例如:
    • 如果插入的数据不符合当前索引顺序(如插入到中间位置),需要进行额外的页面分裂或移动。
    • 如果更新了聚集索引列的值,可能会触发数据的重排甚至移动到不同的页面,导致性能开销增加。
  • 查询优势 聚集索引特别适合范围查询。索引顺序与数据存储顺序一致的特点,使得扫描范围内的数据非常快速,例如按用户ID范围查找用户信息。

应用场景

聚集索引通常适合以下场景:

  • 主键索引 由于主键具有唯一性并涉及数据的一致性,因此通常将主键列设置为聚集索引是一个好的选择。例如,用户表的用户ID作为主键,可以方便地进行按用户ID的单值查询和范围查询。
  • 高频范围查询 如果查询频繁涉及某列的范围查找(如日期范围),可将该列设置为聚集索引。例如,订单表的订单日期作为聚集索引非常适合查询某时间范围内的订单数据。
  • 排序操作优化 如果某列的顺序对查询和结果排序非常重要(如一些时间序列数据),使用聚集索引可以显著减少排序所需的开销,因为数据在存储时已按照索引顺序排好。

非聚集索引(Non-Clustered Index)

非聚集索引是一种独立于表中数据的索引结构,它不会改变表中数据的物理存储顺序。非聚集索引的叶子节点存储的是索引键值和一个指向数据行位置的定位器。这个定位器可以是:

  • 数据行的物理地址(如在某些存储引擎中,例如 MyISAM);或者
  • 主键值(如在 InnoDB 中,非主键索引的定位器会包含主键值,通过主键索引进一步定位数据行)。

因此,通过非聚集索引查询数据时,会首先通过索引键值定位指针,再利用指针找到对应的实际数据行。例如,假设有一个用户表存储了用户姓名和年龄,为姓名列创建了非聚集索引,该索引结构会存储姓名值以及定位到姓名对应数据行的指针。这种设计使得索引的逻辑顺序与表中行的物理存储顺序始终保持独立。

非聚集索引的特性

  • 叶子节点存储指向数据行的定位器 非聚集索引的叶子节点不包含实际的表数据行,而是存储索引键值和指向数据行的定位器。一条索引记录中可能包含索引字段值及多个行定位器(当索引列的值不唯一时),这些定位器用来明确数据行的位置。
  • 逻辑顺序与物理顺序不同 非聚集索引的逻辑排序与表中数据行的物理存储顺序不同。例如,如果表数据按照主键有序存储,而创建了基于姓名的非聚集索引,那么姓名的索引结构中键值会按照字典序排列,但数据表本身的行按照主键值存储。

数据访问方式

使用非聚集索引查询数据时,涉及以下步骤:

  • 定位索引键值 数据库首先在非聚集索引结构中查找满足条件的索引列值。
  • 解析定位器 数据库使用索引项中的定位器指向实际的数据行位置。
  • 访问数据行 最后,数据库根据定位器,从表中获取对应的数据行。

例如,在一个产品表中,如果为产品名称列创建了非聚集索引,当查询某个产品名称的详细信息时,数据库会:

  • 首先从非聚集索引中定位产品名称;
  • 再通过指针找到存储在磁盘其他位置的产品详细信息行。

这意味着非聚集索引访问数据比聚集索引多一步指针跳转,但这种设计适合无须改变表数据物理顺序的场景。

性能开销

非聚集索引的性能影响主要反映在以下几方面:

  1. 存储空间开销 每个非聚集索引都需要额外的空间来存储索引键和值,以及指向数据行的定位器。创建过多的非聚集索引可能会显著增加表的存储开销。
  2. 读取性能
    1. 随机访问性能:非聚集索引尤其适合频繁随机查询单行数据的场景。例如,根据某一列的精确值进行查询(WHERE 列值 = ...),如果有合适的非聚集索引,查询性能会很好。
    2. 范围查询性能:相比于聚集索引,由于非聚集索引访问数据需要多次跳转(从索引到定位器再到数据行),范围查询性能可能略逊于聚集索引。
  3. 更新性能 当表数据的插入、更新或删除影响了非聚集索引列的值时,需要对索引结构重新维护。因此,创建过多的非聚集索引可能会对写入操作性能产生一定的影响。

应用场景

非聚集索引适合以下场景:

  1. 辅助查询列 非聚集索引常用于查询频繁但不是主键的列。例如,在电商的产品表中,用户经常搜索产品名称,而产品名称列可以设置为非聚集索引,便于快速搜索而不会改变主键的数据存储顺序。
  2. 多列查询 当表中的某几列被联合频繁查询时,可以为这些列创建组合非聚集索引。例如,产品表中用户经常通过产品类别和产品价格的组合条件查找,那么可以为 类别 + 价格 创建非聚集索引来优化查询效率。
  3. 减少表数据重排 如果某列查询频率高,但不适合作为主键(例如重复值较多或需要频繁更新),非聚集索引是更优选择。它不会改变表的数据物理顺序,避免重排对性能的不必要影响。

总结

本文系统地介绍了MySQL中两类重要的索引——聚集索引非聚集索引。索引在数据库中的作用类似于书籍目录,能够显著提高数据查询的效率,从而避免全表扫描。

  • 聚集索引:定义了表中数据的物理存储顺序,其叶子节点直接存储数据行,且每个表只能有一个聚集索引。它在范围查询和主键访问方面表现出显著的性能优势,但由于数据行的顺序需要保持与索引列一致,插入和更新操作可能带来额外的性能开销。
  • 非聚集索引:独立于数据的物理存储顺序,其叶子节点存储索引键值和数据行的指针。适合辅助查询列或联合查询场景,不影响表数据的存储顺序,但查询时需要额外跳转,通过指针定位数据行,存储空间和更新性能相较聚集索引略有开销。

在选择索引类型时,应根据表的查询模式、写入频率和查询性能需求来合理规划。聚集索引通常适合主键或高频范围查询,而非聚集索引则适合辅助查询列、联合查询或需要保持表数据存储独立性的场景。通过对索引结构的深入理解,可以构建优化的数据表设计并有效提升查询性能,同时降低存储和操作的成本。



学习MySQL绕不开的两个基础概念:聚集索引与非聚集索引插图

关注公众号:程序新视界,一个让你软实力、硬技术同步提升的平台

除非注明,否则均为程序新视界原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.choupangxia.com/2025/09/16/mysql-clustered-index-and-non-clustered-index/