聚簇索引(Clustered Index)和非聚簇索引 (Non- Clustered Index)

本文深入探讨数据库索引的重要性,解析聚簇索引与非聚簇索引的区别及应用场景,通过实例说明如何通过合理使用索引提升数据库查询效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

索引的重要性
数据库性能优化中索引绝对是一个重量级的因素,可以说,索引使用不当,其它优化措施将毫无意义。

聚簇索引(Clustered Index)和非聚簇索引 (Non- Clustered Index)
最通俗的解释是:聚簇索引的顺序就是数据的物理存储顺序,而对非聚簇索引的索引顺序与数据物理排列顺序无关。举例来说,你翻到新华字典的汉字“爬”那一页就是P开头的部分,这就是物理存储顺序(聚簇索引);而不用你到目录,找到汉字“爬”所在的页码,然后根据页码找到这个字(非聚簇索引)。

聚簇索引的唯一性
正式聚簇索引的顺序就是数据的物理存储顺序,所以一个表最多只能有一个聚簇索引,因为物理存储只能有一个顺序。正因为一个表最多只能有一个聚簇索引,所以它显得更为珍贵,一个表设置什么为聚簇索引对性能很关键。

非聚簇索引

索引节点的叶子页面就好比一片叶子。叶子头便是索引键值。

先创建一张表:

CREATE TABLE `user` ( 
`id` INT NOT NULL ,
`name` VARCHAR NOT NULL ,
`class` VARCHAR NOT NULL);

对于MYISAM引擎,如果创建 id 和 name 为索引。对于下面查询:

select * from user where id = 1

会利用索引,先在索引树中快速检索到 id,但是要想取到id对应行数据,必须找到该行数据在硬盘中的存储位置,因此MYISAM引擎的索引 叶子页面上不仅存储了主键id 还存储着 数据存储的地址信息。如图:

这里写图片描述

像这样的索引就称为非聚簇索引。

非聚簇索引的二级索引与主键索引类似。假设我们对name添加索引,那么name的索引树叶子将是如下结构:

这里写图片描述

 

聚簇索引

对于 非聚簇索引 来说,每次通过索引检索到所需行号后,还需要通过叶子上的磁盘地址去磁盘内取数据(回行)消耗时间。为了优化这部分回行取数据时间,InnoDB 引擎采用了聚簇索引。 
聚簇索引,即将数据存入索引叶子页面上。对于 InnoDB 引擎来说,叶子页面不再存该行对应的地址,而是直接存储数据:

这里写图片描述

这样便避免了回行操作所带来的时间消耗。 使得 InnoDB 在某些查询上比 MyISAM 还要快!

ps. 关于查询时间,一般认为 MyISAM 牺牲了功能换取了性能,查询更快。但事实并不一定如此。多数情况下,MyISAM 确实比 InnoDB 查的快 。但是查询时间受多方面因素影响。InnoDB 查询变慢得原因是因为支持事务、回滚等等,使得 InnoDB的叶子页面实际上还包含有事务id(换句话说就是版本号) 以及回滚指针。

在二级索引方面, InnoDB 与 MyISAM 有很大区别。

InnoDB默认对主键建立聚簇索引。如果你不指定主键,InnoDB会用一个具有唯一且非空值的索引来代替。如果不存在这样的索引,InnoDB会定义一个隐藏的主键,然后对其建立聚簇索引。一般来说,InnoDB 会以聚簇索引的形式来存储实际的数据,它是其它二级索引的基础。

假设对 InnoDB 引擎上表name字段加索引,那么name索引叶子页面则只会存储主键id:

这里写图片描述

检索时,先通过name索引树找到主索引id,再通过id在主索引树的聚簇索引叶子页面取出数据。

### 索引非聚簇索引的区别及实现原理 #### 一、索引Clustered Index) **定义**:索引是一种将数据行与索引定义的逻辑顺序保持一致的索引结构。在 MySQL 的 InnoDB 存储引擎中,表的数据存储实际上是按照主键顺序排列的,主键即为索引[^1]。如果没有显式定义主键,则 InnoDB 会选择一个唯一且非空的列作为索引;如果不存在这样的列,InnoDB 会生成一个隐藏的主键作为索引[^3]。 **实现原理**:索引的叶子节点存储的是实际的数据行,而非指向数据行的指针。这意味着当通过索引查找数据时,可以直接访问到数据本身,而无需额外的查找操作[^4]。 **优点**: - 数据访问效率高,因为数据索引是紧密关联的。 - 对于范围查询特别有效,因为数据按索引顺序物理存储。 **缺点**: - 插入或更新操作可能导致页分裂,从而影响性能。 - 如果主键不是连续递增的,可能会导致数据插入时频繁调整物理存储位置。 --- #### 二、非聚簇索引(Non-Clustered Index) **定义**:非聚簇索引是一种不改变表中数据行物理顺序的索引类型。它的叶子节点存储的是主键值(或行指针),通过这些值再去查找实际的数据行[^2]。 **实现原理**:非聚簇索引的叶子节点包含索引列的值以及指向对应数据行的引用(通常是主键值或行指针)。因此,非聚簇索引需要两次查找操作:首先通过非聚簇索引定位到主键值,然后通过主键值访问实际的数据行[^4]。 **优点**: - 可以创建多个非聚簇索引,满足不同的查询需求。 - 对于频繁更新的表,非聚簇索引的影响较小,因为它不影响数据行的物理存储顺序。 **缺点**: - 查询效率低于索引,因为需要额外的查找操作。 - 额外占用存储空间,因为需要维护索引指向数据行的引用。 --- #### 三、使用场景分析 **索引适用场景**: - 表中存在大量范围查询(如 `BETWEEN` 或 `>` 等条件)。 - 数据的插入顺序接近主键的递增顺序,减少页分裂的可能性。 - 查询经常基于主键进行,因为索引直接存储了数据行。 **非聚簇索引适用场景**: - 表中存在多个查询条件,需要为不同列创建索引- 数据更新频繁,但查询较少依赖于主键。 - 需要为非主键列创建索引以优化查询性能。 --- ```python # 示例代码:创建索引非聚簇索引 CREATE TABLE employees ( id INT PRIMARY KEY AUTO_INCREMENT, # 主键自动成为索引 name VARCHAR(50), department_id INT, INDEX (department_id) # 非聚簇索引 ); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值