Mysql索引(B+Tree)浅谈

首先我们来明确一下索引的定义:

索引是帮助MySQL高效获取数据的排好序的数据结构。

索引一般分为四大类:

FULLTEXT:全文索引

NORMAL:普通索引

SPATIAL :组合索引

UNIQUE :唯一索引(主键索引也是唯一索引的一种)

既然索引是数据结构,那么他究竟采用的是什么数据结构啦。

一般MySQL采用的Hash,B+tree两种数据结构,一般使用B+Tree的索引占据98%以上。

Hash索引通过哈希函数,获取磁盘的物理位置,快速的获取数据。

Hash索引的优点 :在查询单个数据的时候执行效率非常高。

缺点:在执行范围查询的时候效率低下。

  B+Tree是(B-Tree的变种),以下是B+tree的特性

 1、非叶子节点不存储data,只存储索引,可以放更多的索引

 2、叶子节点不存储指针

 3、顺序访问指针,提高区间访问性能

下面图形展示了B+Tree的一个结构

B+Tree中的每一层默认最多存储16个字节的数据。

下面我们来讲一下聚集索引和非聚集索引的区别

聚集索引 以InnoDB作为存储引擎的表,表中的数据都会有一个主键,即使你没有创建组件,MYSQL会自动帮你创建一个隐式主键。这种以主键作为索引值,叶子节点包含所有元素的B+ Tree索引称之为聚集索引。

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

下面我们就分别讲解一下聚集索引和非聚集索引的查找过程。

利用聚集索引查找数据的过程

7

以上B+tree就是典型的聚集索引存储。

现在假设我们需要查找id>=18且id<40的用户数据。以下为对应的SQL语句。

select * from user where id>=18 and id <40

  其中id为主键,查找过程如下

1、一般根节点都是常驻内存的,也就是说页1已经在内存中,我们直接在在内存中读取到页1的数据,找出id>=18 and id <40的数据。我们首先找到id=18的键值。根据指针,定位到页3。

2、根据页1中的p2指针去从磁盘中将页3的数据加载到内存中,然后从页3中查找id>=18 and id <40,我们首页定位到id=18,此时根据页3中的p1指针定位到页8。

3、根据定位将页8的数据从磁盘加载到内存中,并将所有数据与条件id>=18 and id <40,发现页8中的所有数据均满足此条件,根据页8的指针,定位到页9.

4、根据定位将页9的数据从磁盘加载到内存中,并将所有数据与条件id>=18 and id <40,发现页8中的所有数据均满足此条件,根据页10的指针,定位到页10.

5、以此类推知道查找到12页,发现41大于40不满足条件,终止查找。将满足条件的数据从内存中返回。

利用非聚集索引查找数据

9

这个非聚集索引表示的是用户幸运数字的索引,表结构如下

91

在叶子节点中,不再存储所有的数据了,存储的是键值和主键。对于叶子节点中的 x-y,比如 1-1。左边的 1 表示的是索引的键值,右边的 1 表示的是主键值。

查找过程:

1、在页1中找到luckyNum等于18,找到luckyNum=18,通过页1中p2指针定位到页3,。

2、将页3的数据加载到内存中,比较找到luckyNum=31,通过页3中的p3指针定位到页10.

3、将页3的数据加载到内存中,比较找到luckyNum=33,获取数据。找到主键值47。再根据主键值,走一遍聚集索引的查找流程。

根据数据库存储结构,总结如下优化技巧:

1、尽量使用int自增类型作为主键,占用存储空间较小,搜索时比较成功较小。若字符串为主键,增加索引文件大小,切构建索引时,利用索引查询时耗时较长。

2、遵循最左前缀匹配原则

尽量构建组合索引,如存在(a,b,c)三个字段的组合索引,则没有必要单独构建(a)。查询从索引的最左列开始并且不跳过索引中的列。

3、尽量不要where条件中构建了索引的字段上做任何操作(计算,函数,or,类型转换,like ),否则会使索引失效,进行全表扫描。

4、选择唯一性高的字段建立索引(字段中的所以元素都是唯一的)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章