文章目录
一、索引的定义:
索引是帮助MySQL数据库在获取数据时,能高效率去获取指定条件数据的排好序的数据结构
二、索引存储的数据结构选型
2.1、二叉树:
1、说明:结构为小数在树的左分支,大数在树的右分支的存储结构
2、其数据结构如下图:
3、存在的缺陷:
如果索引的数据是依次递增的,那此时的产生的树结构为类似链表结构了,这种结构导致其查询效率得不到明显的提升,所以索引选的数据结构不是二叉树,具体如下图:
2.2、红黑树
1、说明:其结构为小数在树的左分支,大数在树的右分支,具有动态的高度平衡的存储结构
2、其数据结构如下图:
3、存在的缺陷:
红黑树也称为二叉平衡树,相比二叉树,做了左右树分支的动态平衡优化,但随着需要存储的数据量增加,索引数据也是递增的情况下,那红黑树的高度也是随着数据递增而增加,那这种情况下,在这颗红黑树查找数据的效率就受到影响,所以索引选的数据结构也不是红黑树,其存储数据结构如下图:
2.3、hash表
1、说明:其结构为数组+链表+红黑树(JDK1.8后,长度大于等于8=>链表–>红黑树,长度小于6=>红黑树–>链表)的存储结构,数据的初始长度为16,也就是16个hash桶,链表主要是用来解决不同的值发生hash碰撞时的解决方案
2、其数据结构如下图:
3、存在的缺陷:
其hash表结构存储的数据,在查找的数据的时候,效率甚至比树结构的还高,但是其结构对于范围查询的数据却是很不友好(不支持范围查询),只支持精准查询,所以在MySQL底层结构设计时,也不是选hash表作为其索引存储的数据结构
2.4、B-树
1、说明:基于二叉树与红黑树存在的缺陷,B-Trees将数据进行分页存储,一页的大小为大约16K,但是其每个数据中包含了data,data主要存储的是索引数据对应行数据在磁盘文件中的地址信息,那这样子算下来,其一页的数据能存储的数据是不多的,假设一个数据中占的大小了1K,那一页的数据就为16个索引数据
2、其数据结构如下图:
3、存在的缺陷:
- 首先其每页数据的每个索引数据,都包含了data,占用了一定的内存资源,致使每页能存储的索引数据是不多的
- 数据夜与页之间是没建立关联的,如果是范围查询导致跨页数据,那就得扫描目前页数据还得辉根节点重新扫描另外一个页节点数据,查询数据效率受到一定影响
2.5、B+树
1、说明:其结构类似B-Trees,区别于B-Trees的点是:非叶子节点的都不存data(主要是为了能存储更多的索引数据),其非叶子节点的数据其实是冗余索引,他们存在的意义就是为了充当构建B+Trees角色而已,其数据组成是选择下一页的第一个数组成,每一页数据之间其实是有一个双向指针互相指向彼此,其目的是在做范围查询时,可以不用回树根重新对树进行扫描==>前提是索引的定义,排好序的数据结构
2、其数据结构如下图:
3、B+树综合解决了前几个数据结构存在的大部分问题,所以MySQL索引存储的数据结构选择的B+树
三、索引数据存储、查找数据的详解
3.1、索引数据储存方式
3.1.1 聚簇索引(聚集索引)
1、说明:在B+树存储结构中,叶子节点上的data数据存储区域,储存了索引值对应行数据,所以在磁盘中存储的文件就只有两个文件,一个文件是储存数据表结构信息的,另外一个文件则是存储索引以及对应的数据信息
2、索引数据存储时的结构图如下:
3、在数据表的存储引擎中,InnoDB就使用的是聚簇索引存储方式
4、使用索引查找数据时,分为主键索引树查找和非主键索引树查找数据
- 主键查找:直接在主键索引树种查找索引对应的行数据,从而获取数据表数据
- 非主键索引:需要在二级索引树找到对应的主键索引值,再回表获取主键索引值对应的行数据信息
3.1.2 非聚簇索引(非聚集索引)
1、说明:在B+树存储结构中,叶子节点上的data数据存储区域,储存了索引值对应行数据,所以在磁盘中存储的文件就有三个文件,一个文件是储存数据表结构信息的,一个文件是存储索引信息,最后一个文件是存储数据表对应的数据信息
2、索引数据存储时的结构图如下:
3、在数据表的存储引擎中,MyISAM就使用的是非聚簇索引存储方式
4、使用索引查找数据时,无论是主键索引树查找和非主键索引树查找数据,其实都是需要现在索引文件中找数据对应的数据在磁盘中的存储位置,再到数据文件中获取到数据
四、拓展与部分说明
1、部分说明
- B+树一页数据选择16KB左右,是因为如果索引字段按照bigint来计算,加上存储地址的大小那就是(8+6)B,算下来一页数据大概能放1170个元素,如果树的高度是3,叶子节点包含了data,会占内存较多,就按1KB来计算,叶子节点一页数据就可以放16个元素,那叶子节点能存放的总数大概为两千多万,树的高度为3,能存储的索引数量大概在两千多万,是比较合适的一个选择
- 在建表时,为什么DBA会建议都需要建立主键索引以及以int类型自增为索引:
首先,第一个点,建立主键索引,是为了避免这种简单的操作由MySQL数据库来给我们做,如果我们不建立主键索引,那数据库也是会先选择数据的某一列不存在重复的数据作为主键索引列,如果都没有这种数据列存在,那MySQL数据库会自己模拟出一列,例如rowid作为主键索引列来作为主键索引列;
其次,建议用int自增作为主键索引,是从构建索引树考虑的,一方面是在构建索引树的时候,索引数据是需要排序的,选数字类型的,在排序上会快很多,况且还是自增的,另一方面就是从占用磁盘内存考虑,因为索引数据是需要存再磁盘的,数字类型占用空间不大,在一定程度上可以节省空间; - 在非主键索引的叶子节点只存储主键索引值的原因是==>一方面是考虑数据的一致性,改变主键索引中的某数据值,那非主键索引这边不需要再次改动,数据是保持一致的,另一方面是考虑节省磁盘空间;
2、拓展
2.1 非聚簇索引和聚簇索引的区别
- 数据文件数量不一致,聚簇索引索引只包含了.frm(表结构)和.ibd(索引+数据),但是非聚簇索引中存在.frm(表结构),.MYD(数据),.MYI(索引)
- 索引树的叶子节点存储的数据不同,聚簇索引树的叶子节点存的key是索引值,value是索引值对应的行数据,非聚簇索引树的叶子节点存的key虽然也是索引值,但是value存储场是当前索引值对应的行数据在磁盘中的位置信息,需要将这个值到文件.MYD中获取
2.2 MySQL的存储引擎InnoDB和MyISAM区别
2.2.1 MyISAM
- 不支持事物,但是每一次查询都是原子操作的
- 只支持表级锁
- 维护了表数据的总行数
- 存储的数据文件有三个.frm(表结构),.MYD(数据),.MYI(索引)
2.2.2 InnoDB
- 支持ACID事物,支持事物的四种隔离级别
- 支持行级锁以及外键约束
- 但是不维护数据表的总行数