Mysql 聚簇索引和非聚簇索引的区别

本文详细介绍了Mysql中的聚簇索引和非聚簇索引的区别,聚簇索引将数据与索引存储在一起,非聚簇索引则分开存储。每个表只有一个聚簇索引,可以有多个非聚簇索引。在InnoDB中,辅助索引叶子节点存储主键值,通过主键检索数据更高效,因为数据和索引在同一页面,而辅助索引需要二次查找。聚簇索引适用于频繁主键查询,而非聚簇索引在全表扫描和排序上有优势。

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

聚簇索引是对磁盘上实际数据重新组织以按指定的一个或多个列的值排序的算法。特点是存储数据的顺序和索引顺序一致。
一般情况下主键会默认创建聚簇索引,且一张表只允许存在一个聚簇索引。

在《数据库原理》一书中是这么解释聚簇索引和非聚簇索引的区别的:
聚簇索引的叶子节点就是数据节点,而非聚簇索引的叶子节点仍然是索引节点,只不过有指向对应数据块的指针。

MYSQL索引:对聚簇索引和非聚簇索引的认识_alex大喵的博客-CSDN博客_mysql 聚簇索引和非聚簇索引的区别

聚簇索引:将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据【每个表都有且只有一个聚簇索引】

非聚簇索引:将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置【每个表都可以没有非聚簇索引,也可以有多个非聚簇索引】

在innodb中,在聚簇索引之上创建的索引称之为辅助索引,非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引。辅助索引叶子节点存储的不再是行的物理位置,而是主键值,辅助索引访问数据总是需要二次查找

  1. InnoDB中,聚簇索引将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。
  2. 若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。(重点在于通过其他键需要建立辅助索引)

聚簇索引具有唯一性,由于聚簇索引是将数据跟索引结构放到一块,因此一个表仅有一个聚簇索引。

表中行的物理顺序和索引中行的物理顺序是相同的在创建任何非聚簇索引之前创建聚簇索引,这是因为聚簇索引改变了表中行的物理顺序,数据行 按照一定的顺序排列,并且自动维护这个顺序;

聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一且非空的索引代替。如果没有这样的索引,InnoDB 会隐式定义一个主键(类似oracle中的RowId)来作为聚簇索引。如果已经设置了主键为聚簇索引又希望再单独设置聚簇索引,必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可。

MyISAM中聚簇/非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树

使用聚簇索引的优势:

每次使用辅助索引检索都要经过两次B+树查找,看上去聚簇索引的效率明显要低于非聚簇索引,这不是多此一举吗?聚簇索引的优势在哪?

1.由于行数据和聚簇索引的叶子节点存储在一起,同一页中会有多条行数据,访问同一数据页不同行记录时,已经把页加载到了Buffer中(缓存器),再次访问时,会在内存中完成访问,不必访问磁盘。这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来组织数据,获得数据更快。

2.辅助索引的叶子节点,存储主键值,而不是数据的存放地址。好处是当行数据放生变化时,索引树的节点也需要分裂变化;或者是我们需要查找的数据,在上一次IO读写的缓存中没有,需要发生一次新的IO操作时,可以避免对辅助索引的维护工作,只需要维护聚簇索引树就好了。另一个好处是,因为辅助索引存放的是主键值,减少了辅助索引占用的存储空间大小。

注:我们知道一次io读写,可以获取到16K大小的资源,我们称之为读取到的数据区域为Page。而我们的B树,B+树的索引结构,叶子节点上存放好多个关键字(索引值)和对应的数据,都会在一次IO操作中被读取到缓存中,所以在访问同一个页中的不同记录时,会在内存里操作,而不用再次进行IO操作了。除非发生了页的分裂,即要查询的行数据不在上次IO操作的换村里,才会触发新的IO操作。

3.因为MyISAM的主索引并非聚簇索引,那么他的数据的物理地址必然是凌乱的,拿到这些物理地址,按照合适的算法进行I/O读取,于是开始不停的寻道不停的旋转。聚簇索引则只需一次I/O。(强烈的对比)

4.不过,如果涉及到大数据量的排序、全表扫描、count之类的操作的话,还是MyISAM占优势些,因为索引所占空间小,这些操作是需要在内存中完成的。

聚簇索引需要注意的地方

当使用主键为聚簇索引时,主键最好不要使用uuid,因为uuid的值太过离散,不适合排序且可能出线新增加记录的uuid,会插入在索引树中间的位置,导致索引树调整复杂度变大,消耗更多的时间和资源。

建议使用int类型的自增,方便排序并且默认会在索引树的末尾增加主键值,对索引树的结构影响最小。而且,主键值占用的存储空间越大,辅助索引中保存的主键值也会跟着变大,占用存储空间,也会影响到IO操作读取到的数据量。

为什么主键通常建议使用自增id

聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。如果主键不是自增id,那么可以想 象,它会干些什么,不断地调整数据的物理地址、分页,当然也有其他一些措施来减少这些操作,但却无法彻底避免。但,如果是自增的,那就简单了,它只需要一 页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。

在一张表上最多只能创建一个聚集索引,因为真实数据的物理顺序只能有一种。

InnoDB的默认数据结构是聚簇索引,而MyISAM是非聚簇索引。

存储引擎是InnoDB, 在data目录下会看到2类文件:.frm、.ibd
(1)*.frm--表结构的文件。
(2)*.ibd--表数据文件(存储数据和索引)
 
存储引擎是MyISAM, 在data目录下会看到3类文件:.frm、.myi、.myd 
(1)*.frm--表定义,是描述表结构的文件。
(2)*.MYD--"D"数据信息文件,是表的数据文件。
(3)*.MYI--"I"索引信息文件,是表数据文件中任何索引的数据树

MyISAM引擎可以不设置主键。InnoDB引擎是必须设置主键的,需要依赖主键生成聚簇索引。 

因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL 系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。

https://segmentfault.com/a/1190000022206424

MySQL索引:聚簇索引和非聚簇索引的区别_baidu_15952103的博客-CSDN博客_聚簇索引和非聚簇索引的区别

聚簇索引与非聚簇索引的区别-白红宇的个人博客

MySQL中myisam和innodb的主键索引有什么区别?_欧辰的专栏-CSDN博客_myisam有主键索引吗

转自:https://my.oschina.net/xiaoyoung/blog/3046779

### 索引非聚簇索引区别及实现原理 #### 一、索引(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、付费专栏及课程。

余额充值