数据库之聚簇索引和非聚簇索引的区别

本文介绍了数据库中聚簇索引和非聚簇索引的概念与区别。聚簇索引决定了表的物理排列顺序,一个表只能有一个聚簇索引,叶子节点包含了完整行数据。非聚簇索引则存储数据的指针,可有多个。MySQL的InnoDB使用聚簇索引,MyISAM使用非聚簇索引。在InnoDB中,辅助索引需通过主键索引获取完整行数据,而MyISAM索引直接指向数据物理块。

聚簇索引(密集索引)文件中的每个搜索码值都对应一个索引值(叶子节点不仅保存了键值,还保存了位于同一行记录中的其他列的信息),因为聚簇索引决定了表的物理排列顺序,而一个表只能有一种物理排列顺序,所以一个表只能创建一个聚簇索引。

非聚簇索引(稀疏索引)文件只为索引码的某些值建立索引项(叶子节点仅保存了键值以及该行数据的地址)。

数据库必须要有索引,没有索引则检索过程变成了顺序查找(全表扫描),O(n)的时间复杂度几乎是不能忍受的。我们非常容易想象出一个只有单关键字组成的表如何使用B+树进行索引,只要将这个关键字存储到B+树的节点即可。当数据库一条记录里包含多个字段时,一棵B+树就只能存储主键,如果检索的是非主键字段,则主键索引失去作用,又变成顺序查找(全表扫描)了。这时应该在第二个要检索的列上建立第二套索引(辅助键索引),这个索引由独立的B+树来组织。有两种常见的方法可以解决多个B+树访问同一套表数据的问题,一种叫做聚簇索引(数据和索引存储在一块,索引结构的叶子节点保存了行数据),一种叫做非聚簇索引(数据和索引分开存储,索引结构的叶子节点存储的是指向存放数据的物理块的指针)。

目前,MySQL数据库使用的比较主流的存储引擎有InnoDB和MyISAM,其中InnoDB存储引擎使用的是聚簇索引,而MyISAM存储引擎使用的是非聚簇索引。

InnoDB存储引擎使用聚簇索引并且有且仅有一个聚簇索引(因为聚簇索引决定了表的物理排列顺序,而一个表只能有一种物理排列顺序,因此一个表只能创建一个聚簇索引)。若有一个主键被定义,则该主键作为聚簇索引;若没有主键被定义,则该表的第一个唯一非空索引作为聚簇索引;如果不满足以上条件(没有定义主键,也没有合适的唯一索引),则该表会自动生成一个隐藏主键作为聚簇索引。InnoDB存储引擎必须要有一个主键,且该主键必须作为聚簇索引。

MyISAM存储引擎中的主键索引、唯一索引、普通索引都是非聚簇索引。

如图所示是一张包含2个列的表(以col1作为primary key):
在这里插入图片描述
在InnoDB存储引擎中,主键索引的B+树的叶子节点存储了主键值、事务ID(Transaction ID, TID)、回滚指针(Rollback Pointer, RP,用于支持事务和MVCC)以及该行记录中其他列的值。
在这里插入图片描述
在InnoDB存储引擎中,辅助键索引(二级索引)的B+树的叶子节点存储了Key字段和主键值。
在这里插入图片描述
在MyISAM存储引擎中,是按照列值和行号来组织索引的,其B+树的叶子节点存储了指向存放数据的物理块的指针。
在这里插入图片描述
InnoDB使用的是聚簇索引。将主键组织到一棵B+树(这棵B+树称为主键索引的B+树)中,这棵B+树的非叶子节点只存储了主键值,而行数据(主键的值和其他非主键的列的值)则存储在这棵B+树的叶子节点上,若使用"where id = 14"这样的搜索条件(过滤条件)查找主键(id列),则直接按照主键索引的B+树的检索算法即可查找到对应的叶子节点,之后获得整个行数据。若对Name列(非主键的列)进行条件搜索,则需要两个步骤:第一步在辅助键索引(二级索引)的B+树中检索Name,到达其叶子节点获取对应的主键值(id)。第二步使用找到的主键值(id)在主键索引的B+树中再执行一次B+树的检索操作,最终到达叶子节点即可获取对应的整个行数据。在InnoDB存储引擎中,主键索引的B+树的叶子节点存储了主键值(primary key column)、事务ID(transaction ID,TID)、回滚指针(rollback pointer,RP,用于支持事务和MVCC)和其他非主键的列的值;辅助键索引(二级索引)的B+树的叶子节点存储了Key字段和主键值。

MyISAM使用的是非聚簇索引。非聚簇索引的两棵B+树看上去没有什么不同,节点的结构完全一致,只是存储的内容不同而已。主键索引的B+树的节点存储了主键,辅助键索引(二级索引)的B+树的节点存储了辅助键。表数据存储在独立的地方,这两棵B+树的叶子节点都使用一个指针指向真正的表数据,对于表数据来说,这两个键(主键和辅助键)没有任何差别。由于这两棵索引树是独立的,通过辅助键索引(二级索引)无需访问主键索引的索引树。在MyISAM的存储引擎中,其主键索引和辅助键索引(二级索引)没有任何区别,都是按照列值和行号来组织索引的,在叶子节点处保存的都是指向存放数据的物理块的指针(数据的物理地址),其主键索引仅仅只是一个名为primary的唯一的非空的索引,且MyISAM可以不设置主键。从MyISAM存储的物理文件中我们也能看出,MyISAM存储引擎的索引文件(.MYI)和数据文件(.MYD)是相互独立的。
在这里插入图片描述
在这里插入图片描述

<think> 嗯,用户现在转向了数据库索引的问题,特别是索引非聚簇索引区别。之前用户的多选题是关于Git的fetchpull,现在突然切换主题,可能是学习内容发生了变化,或者是遇到了数据库相关的实际问题。 从引用材料看,用户已经收集了相当全面的资料(包括索引的物理有序性、叶子节点存储数据、非聚簇索引需要回表等核心点),说明ta做过预习。但用户特意强调“不是真正需求”,暗示希望我更深入解释而非简单复述引用内容。 用户可能卡在以下几个潜在问题上: 1. **混淆概念**:比如误以为“一个表只能有一个索引”(实际是只能有一个索引,但可以有多个非聚簇索引)。 2. **性能疑惑**:为什么查询有时走非聚簇索引反而慢?可能没理解回表开销。 3. **设计纠结**:主键用自增ID还是UUID?这关系到索引的插入效率。 我需要重点展开三点: - **物理存储差异**:用书本比喻(索引像字典正文按拼音排,非聚簇索引像部首检字表)。 - **操作代价对比**:插入数据时,索引可能触发页分裂,而非聚簇索引只需追加索引记录。 - **实战示例**:用户对“回表查询”可能无感,需要模拟一个SELECT语句的IO过程。 注意事项: - 严格遵循LaTeX格式(如B+树高度公式$h=\log_dN$)。 - 避免堆砌术语,用“数据页”“指针”等基础词汇解释。 - 补充InnoDB的适配场景(OLTP vs OLAP),因为用户引用提到InnoDB引擎。 最后生成的“相关问题”要有递进性:从原理(为什么非聚簇索引叶子存主键)到实践(如何避免回表),覆盖不同层次需求。 </think> ### 索引非聚簇索引核心解析 #### **1. 物理存储差异** - **索引** - 叶子节点直接存储**完整数据行**(数据页) - 表数据按索引键值**物理有序存储** - 一个表仅能有一个索引(通常为主键) - 示例:`InnoDB`引擎中主键索引索引[^4] - **非聚簇索引** - 叶子节点存储**索引键值 + 主键指针** - 表数据物理存储**与索引顺序无关** - 一个表可创建多个非聚簇索引 - 示例:`MyISAM`引擎的所有索引均为非聚簇索引[^2] > **存储结构对比**: > $$ > \begin{cases} > \text{索引} &: \text{索引页} \rightarrow \text{数据页} \\ > \text{非聚簇索引} &: \text{索引页} \rightarrow \text{主键值} \rightarrow \text{数据页} > \end{cases} > $$ --- #### **2. 查询性能关键点** | **操作** | 索引 | 非聚簇索引 | |------------------|----------------------------|---------------------------| | **等值查询** | 直达数据页(O(1)层级访问) | 需二次查找(回表查询)[^4] | | **范围查询** | 连续磁盘读取(高效) | 随机I/O(性能较低) | | **覆盖索引** | 天然覆盖 | 需索引包含查询字段 | **回表示例**: ```sql SELECT name FROM users WHERE email = 'test@example.com'; ``` 若对`email`建非聚簇索引: 1. 在`email`索引树中找到主键`id` 2. 用`id`回索引树取`name`列 → **额外I/O开销**[^4] --- #### **3. 索引类型与适用场景** - **索引优势** - 范围查询(如`BETWEEN`、`>`) - 排序操作(数据物理有序) - 减少I/O(避免回表) - **非聚簇索引优势** - 高频等值查询(如`WHERE status=1`) - 多维度查询(可建多个辅助索引) - 覆盖索引优化(索引包含查询字段) > ⚠️ **代价权衡**: > - 索引插入/更新可能触发**页分裂**(数据重排) > - 非聚簇索引增加**写放大**(需同步更新索引树) --- #### **4. 经典误区澄清** - ❌ "索引更快" → ✔️ **取决于查询类型**(范围查询优,点查非可能更快) - ❌ "非聚簇索引不存数据" → ✔️ 存储**主键指针**而非数据行[^1][^2] - ❌ "MyISAM没有索引" → ✔️ **所有索引均为非**(数据与索引分离存储) --- ### 总结对比表 | **特性** | 索引 | 非聚簇索引 | |------------------|-------------------------|-------------------------| | 叶子节点内容 | 完整数据行 | 主键指针 | | 数据物理顺序 | 与索引一致 | 无关 | | 索引数量限制 | 仅1个 | 多个 | | 二级索引依赖 | 指向主键 | 独立存储 | | 典型应用场景 | 主键、范围扫描 | 高频过滤条件、覆盖索引 | > 💡 **设计建议**:主键优先选用自增整数(减少索引页分裂),高频查询字段建非聚簇索引并利用覆盖索引避免回表[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值