【mysql】聚簇索引(聚集索引)和非聚簇索引(二级索引、辅助索引)的区别

  • Post author:
  • Post category:mysql




总结

聚簇索引也叫

聚集索引

。,并不是一种单独的索引类型,而是一种数据存储方式。那么可以理解聚簇索引是一种抽象概念,在具体实现的时候,

需要区分不同的引擎

,不同的引擎,实现细节有所不同。


不同的引擎有不同的实现, 很多文章忽略了区分引擎,因此让人很迷惑。


那么什么是聚簇索引?



聚簇索引的叶子节点就是数据节点,也就是说索引和数据行在一起;反之,如果叶子节点没有存储数据行,那么就是非聚簇索引。


二级索引,又称作辅助索引,均属于非聚簇索引

如果反过来说,非聚簇索引就是二级索引,这种说法完全就是错误的。就像学生是人,但是人是学生就不对。

在mysql数据库中,myisam引擎和innodb引擎使用的索引类型不同,

myisam对应的是非聚簇索引

,而

innodb对应的是聚簇索引



1. 聚簇索引

《高性能MySQL》上说聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。那么mysql有哪些索引类型呢,参见

《Mysql目前主要的几种索引类型》

例如,某个冒泡排序算法,对应这里的存储方式,是排序的算法的一种概念,你可以用java写出这个算法,也可以用c写出这个算法,具体语言,对应这里的索引类型。

聚簇索引的叶子节点就是数据节点,也就是说索引和数据行在一起。

那么采用聚簇索引架构的innodb来说,他的叶子节点和数据行就是在一起的。我们来看下innodb B+树的实现:

在这里插入图片描述


一个表只能有一个聚簇索引。

我们知道聚簇索引中包含了数据行,那么如果有多个聚簇索引,就说明存储了多份相同的数据行,岂不浪费空间?

联想

innodb

的存储文件,在一个数据table中,它的

数据文件和索引文件是同一个文件

。即在查询过程中,

找到了索引,便找到了数据文件

。这也间接说明

innodb

采用的是聚簇索引。

聚簇索引默认由主键实现(用主键作为B+树的key,并且把数据行绑定在叶子节点)。

如果表中没有定义主键A,InnoDB 会选择一个

唯一且非空的列

B代替(主键A的特性就是唯一且非空,如果把主键A比作嫡长子,那么列B就是其他儿子,只是继承的顺序靠后,但毕竟也是有皇家血脉的,没有嫡长子,就拿其他儿子当继承人了)。

如果没有这样的列B,InnoDB 会

隐式定义一个主键

(类似oracle中的RowId)来作为聚簇索引。


如果已经设置了主键为聚簇索引又希望再单独设置聚簇索引,必须先删除主键,然后添加我们想要的聚簇索引,最后恢复设置主键即可。



一个坑

在一篇文章中有如下介绍,说法是不准确的:

“在《数据库原理》一书中是这么解释聚簇索引和非聚簇索引的区别的:

聚簇索引的叶子节点就是数据节点,而非聚簇索引的叶子节点仍然是索引节点,只不过有指向对应数据块的

指针



我们知道聚簇索引是一个概念,那么非聚簇索引自然也是一个概念,需要明确指出的是InnoDB和myisam均用到非聚簇索引,但是他们有不同的实现。

因此上面引用的话中,对非聚簇索引的描述”

只不过有指向对应数据块的

指针


”,特指myisam的非聚簇索引实现,而对于innodb的非聚簇索引实现,data指向的是主键值(通过主键值,去聚簇索引进行索引操作,找到叶子节点,数据在该叶子节点上,这个过程好像叫

回表

),不是数据行,也不是指针。

当初没明白这些道理时,被搞的要吐血了



2. 非聚簇索引

由前文知道,myisam采用非聚簇索引实现,那么我们来看下具体是怎么实现的。

在myisam中,一个数据表table的存储文件,它是由

table.frm、table.myd

以及

table.myi

组成。table.myd记录了数据(数据行),table.myi记录了索引的数据。

myisam引擎的索引文件和数据文件是独立分开的,正好符合非聚簇索引的架构。

MyISM使用的是非聚簇索引,

非聚簇索引和InnoDB的聚簇索引这两棵B+树看上去没什么不同

,节点的结构完全一致,只是存储的内容不同而已,InnoDB主键聚簇索引B+树的节点存储了

主键和数据行

,MyISM非聚簇索引B+树存储了

主键和指向data的指针

在这里插入图片描述



3. 二级索引

二级索引,又被称为辅助索引,在不同存储引擎中的内容不同。


InnoDB

中的

二级索引

存放的是

主键值

,如果需要查询对应的数据行,需要

回表查询

,即在聚簇索引中进一步查找对应的数据行。这样可以避免在行移动或者插入新数据时出现的页分裂问题。

InnoDB的二级索引更详细信息,可以参见

《InnoDB二级索引(辅助索引)》


MyISAM



无论是主键索引还是二级索引



索引的叶子节点存放的都是指向数据行的指针

,保证可以通过索引进而查找到对应的数据行,只需要对索引进行一遍查找。这样会存在页分裂问题。

参考:


《聚簇索引和非聚簇索引的区别》

开篇定义聚簇索引那句话


《Mysql聚簇索引和非聚簇索引》

参考主体,但“聚簇索引也叫复合索引”描述是错误的


《MySQL-聚簇索引》

《高性能MySQ》一书的笔记


《mysql聚簇索引详解》

好像也是《高性能MySQ》的笔记


《聚簇索引与非聚簇索引(也叫二级索引)》



《mysql——二级索引(辅助索引)》

二级索引作用


《MySQL在Innodb和MyISAM中的二级索引》



版权声明:本文为m0_45406092原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。