聚簇索引和非聚簇索引

本文详细介绍了MySQL中MyISAM和InnoDB两种存储引擎的索引实现。MyISAM索引文件和数据文件分离,主键索引存储磁盘地址;InnoDB则将数据和索引集成,采用聚集索引,主键索引的叶子节点存储完整数据。InnoDB的辅助索引存储主键值,通过回表找到对应数据。聚集索引在范围查询中表现出色,但非聚集索引可能导致回表操作。建议为InnoDB表设置整型自增主键以优化性能。

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

一、MyISAM存储引擎索引实现

1.1 存储位置

1.2 MyISAM索引结构

MyISAM索引文件和数据文件是分离的(非聚集)

MyISAM引擎,叶子节点的data存的是索引所在行的磁盘空间地址。

MyISAM引擎,它的主键索引,跟数据是分开存储的,它存储的是数据对应的磁盘空间地址,跟数据没有放在一起,这种就叫做非聚集索引,也叫非聚簇索引

1.3、MyISAM索引查找过程

假如有一个sql select * from table where Col1 = 30;

mysql先判断Col1是不是索引,如果是,在这个树上进行判断,定位到叶子节点30,然后,取出磁盘空间地址。

拿出来之后,到MYD文件中,快速的定位到磁盘空间地址,把这行数据拿出来。

二、InnoDb存储引擎索引实现

2.1 存储位置

对于MySQL的InnoDB存储引擎,它有两个文件,frm存储表结构,Ibd文件既存储索引,又存储数据。

2.2 InnoDB索引结构

表数据文件本身就是按B+Tree组织的一个索引结构文件

聚集索引-叶子节点包含了完整的数据记录

非叶子节点不存储data,只存储索引(冗余),可以放更多的索引

叶子节点包含所有索引字段

叶子节点用指针连接,提高范围查找性能

为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)

与MyISAM不同,InnoDB叶子节点,存的是列数据,不再是索引所在行的磁盘空间地址。

这里就引出了聚集索引:

聚集索引,也就是聚簇索引,叶子节点包含了完整的数据记录,也就是说,你的索引,包括你的索引所在行的其他数据,都是放在一起的。这就是聚集索引

InnoDB的主键索引,它就是聚集索引

2.3 问题

为什么建议InnoDB表必须建主键,并且推荐使用整型 自增主键?

InnoDB底层要靠主键,来组织数据表数据,通俗点,就是要靠主键,来维护这个B+树。

但是,当我们对一张表不建主键时,发现也没有报错。其实,是Mysql底层为我们做了这件事。

它会看我们的每一列是否有唯一的这些数据列,如果有,就用这一列来组织树结构

假如,连这个唯一的数据列也没有,那么,它会建一个唯一的隐藏列row_id,来维护B+树。

Mysql本身资源就很紧张了,所以,这些我们能做的一定要尽量做,尽量建立主键,

为什么要保证是整型且自增呢?

因为,mysql插入以及维护的时候,是有序的。

在查找数据的时候,会牵扯到很多比较,整型比大小,相比于uuid之类的字符串比大小要快的多。另外,整型相比于uuid类似的字符串,会更加节省空间。

假如,不是自增插入,由于B+树要维护索引的有序性,如果插入到之前页的数据,但是这些页16KB已经满了,就会涉及到B+树的分裂,影响性能。

如果,都是用自增的,每次都是往现有数据的后面插入数据。

B+Tree为什么可以提高范围查询性能?

首先,Mysql是一个排好序的数据结构,叶子节点都有一个双向指针进行连接。

假如,我们要查找col>20这些数据,我们可以先查col=20对应叶子节点的位置,定位到以后,由于都是排好序的,只需要依次往后遍历即可查出所有。

对于col<20,也是一样,因为叶子节点存有向前的指针,也是可以很方便查出所有数据。

2.4 辅助索引

辅助索引,也叫二级索引,它的叶子节点存储的是我们主键

那为什么Mysql要这么涉及,为什么不像主键索引那样,依旧做聚集索引呢?

因为,节省空间,对于我们的数据项是很耗费空间的,所以,mysql对于,二级索引,叶子节点直接存储主键索引,然后,再根据查找到的主键索引,到主键索引树里,查找对应的记录,这个过程叫做回表。

三、聚簇索引和非聚簇索引

mysql的innodb引擎的聚集索引和非聚集索引网上看到很多资料,有的叫innodb的索引为聚集索引,有的叫做聚簇索引,其实都是一样的,只是在翻译过来了时候命名产生了分歧,聚簇(集)索引的叶子节点就是数据节点

非聚簇(集)索引的叶子节点仍然是索引节点,只不过有指向对应数据块的指针。非聚簇(集)索引在innodb引擎中,又叫做二级索引,辅助索引等。

聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。术语‘聚簇’表示数据行和相邻的键值聚簇的存储在一起。如下图,左侧的索引就是聚簇索引,因为数据行在磁盘的排列和索引排序保持一致。、

(1)聚集索引(聚簇索引)

以 InnoDB 作为存储引擎的表,表中的数据都会有一个主键,即使你不创建主键,系统也会帮你创建一个隐式的主键

这是因为 InnoDB 是把数据存放在 B+ 树中的,而 B+ 树的键值就是主键,在 B+ 树的叶子节点中,存储了表中所有的数据

这种以主键作为 B+ 树索引的键值而构建的 B+ 树索引,我们称之为聚集索引。

(2)非聚集索引(非聚簇索引)

以主键以外的列值作为键值构建的 B+ 树索引,我们称之为非聚集索引。

非聚集索引与聚集索引的区别在于

非聚集索引的叶子节点不存储表中的数据,而是存储该列对应的主键,想要查找数据我们还需要根据主键再去聚集索引中进行查找,这个再根据聚集索引查找数据的过程,我们称为回表

明白了聚集索引和非聚集索引的定义,我们应该明白这样一句话:数据即索引,索引即数据。

聚簇索引的好处:

按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多个数据块中提取数据,所以节省了大量的io 操作

聚簇索引的限制:

对于mysql 数据库目前只有innodb 数据引擎支持聚簇索引,而Myisam 并不支持聚簇索引。由于数据物理存储排序方式只能有一种,所以每个Mysql 的表只能有一个聚簇索引一般情况下就是该表的主键

为了充分利用聚簇索引的聚簇的特性,所以innodb 表的主键列尽量选用有序的顺序id,而不建议用无序的id,比如uuid 这种

参考参考视频教程索引

### 索引非聚簇索引的区别 #### 定义 索引(Clustered Index)是指表中的物理数据存储顺序与索引键值的逻辑顺序一致[^3]。这意味着当创建了一个索引后,数据库会按照索引键重新排列实际的数据行位置。 而非聚簇索引(Non-clustered Index),其叶子节点并不包含真正的数据记录本身,而是包含了指向对应数据行的一个指针或者ROWID。这样即使通过非聚簇索引来访问数据,也需要额外的一次查找操作来获取完整的数据行信息。 #### 工作原理 对于 **索引** 来说,由于它决定了表中数据的实际存储方式,所以每张表只能有一个索引。这是因为数据行的位置一旦被固定下来就难以再改变其他排序规则。通常情况下,在InnoDB引擎下主键即默认作为索引存在;如果没有显式定义主键,则会选择一个唯一且非空的字段自动构建为主键并形成索引。 相比之下,**非聚簇索引** 的实现更加灵活多样。它们不会影响原始表格里数据项之间的相对布局关系,只是单纯地建立了一种映射机制用于加速特定类型的检索过程。每当新增加一条新纪录时,只需简单更新相应的辅助索引结构而无需调整整个磁盘文件上的内容摆放格局。 #### 应用场景分析 ##### 索引的应用场合: - 当频繁执行基于某些列值范围内的扫描查询时,采用索引能够显著减少I/O次数从而提高效率[^1]。 - 对于那些经常需要按某种自然顺序读取大量连续行的操作而言非常适合设置成形式。 ##### 非聚簇索引更适合下面这些情况之一者选用: - 如果应用程序主要依赖精确匹配而不是区间搜索的话那么利用覆盖索引技术就可以完全避免回表动作进而提升速度[^2]。 - 存在多维度过滤条件但又不可能全部组合起来构成复合型主关键字的情况下单独设立几个独立的小规模二级索引往往更为经济实用一些. ```sql -- 创建索引的例子 (假设使用的是支持此功能的关系型数据库系统) CREATE TABLE employees ( id INT NOT NULL, name VARCHAR(50), department_id INT, PRIMARY KEY(id) -- 这里的主键实际上就是一种特殊的索引 ); -- 添加非聚簇索引实例 ALTER TABLE employees ADD INDEX idx_department(department_id); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值