数据库知识——MySQL索引结构B+tree

一般在项目中做报表功能的人都会遇到sql查询慢的问题。这时候很多人都会选择给合适的字段创建索引。

那么索引为什么加快sql查询呢?现在来看看什么是mysql索引

一、什么是索引?

索引是为了加速对表中数据行的检索和创建的一种分散存储的数据结构

很多人在面试的时候说索引是书的目录之类的答案。其实很多面试官不是要你回答这种模糊的概念。记住:索引是一种数据结构

索引上面储存这表数据在磁盘中的地址。如下图:

二、为什么要用索引?

1、索引能极大的减少存储引擎需要扫面的数据量

2、索引可以把随机io变成顺序IO

3、索引可以帮助我们进行分组、排序等操作时,避免使用临时表

这些功能都和索引的数据结构有关

三、索引的数据机构是什么?

自己创建过索引的人都知道索引的数据机构有B-Tree 索引(技术上说B+tree), Hash 索引, Fulltext 索引和 R-Tree 索引

他们之间的区别这里不谈。

四、Btree和B+tree的区别

Btree的数据结构如图:

btree1

特性:

关键字集合分布在整颗树中;

任何一个关键字出现且只出现在一个结点中;

搜索有可能在非叶子结点结束;

其搜索性能等价于在关键字全集内做一次二分查找;

自动层次控制;

查询原理:

B-树的搜索,从根结点开始,对结点内的关键字(有序)序列进行二分查找,如果命中则结束,否则进入查询关键字所属范围的儿子结点;重复,直到所对应的儿子指针为空,或已经是叶子结点;因此,B-Tree的查找过程是一个顺指针查找结点和在结点的关键字中进行查找的交叉进行的过程。

B+trees是B trees的进化版

它的数据结构如图:

alt

特性:

所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;

不可能在非叶子结点命中;

非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层;

更适合文件索引系统

查询:

循叶结点链顺序搜索

另一种是从根结点开始,进行自顶向下,直至叶结点的随机搜索

区别总结:

1、B+节点关键字个数与子节点个数是1:1的关系,B+采用闭合区间

2、B+非叶节点不保存数据相关信息,只保存关键字和子节点的引用

3、B+关键字对应的数据保存在叶子节点中

4、B+叶子节点是顺序排列的,并且相邻节点具有顺序引用的关系(链表)

五、为什么使用B+tree?

1、B+树是B树的变种,拥有B树的优势

2、B+树的扫库能力更强

3、B+树的磁盘读写能力更强

4、B+树的排序能力更强(叶子节点中的数据引用顺序排列)

5、B+树的查询效率更稳定(所有数据引用都在叶子节点)

六、mysql B+tree的体现形式(在myisam和innodb中的体现):

1、myisam:

在数据文件中会生成三个文件:table_name.frm(存放建表中信息包括字段等等)table_name.myi(存放索引)table_name.myd(存放数据)

主键索引:
MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。下图是MyISAM主键索引的原理图:

这里设表一共有三列,假设我们以Col1为主键,图myisam1是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址。

辅键索引:

在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在Col2上建立一个辅助索引,则此索引的结构如下图所示:

同样也是一颗B+Tree,data域保存数据记录的地址。因此,MyISAM中索引检索的算法为首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录。

MyISAM的索引方式也叫做“非聚集”的,之所以这么称呼是为了与InnoDB的聚集索引区分。

2、innodb

在数据文件中有两个文件:table_name.frm table_name.idb

主键索引:

MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

上图是InnoDB主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形

辅键索引:

InnoDB的所有辅助索引都引用主键作为data域。例如,下图为定义在Col3上的一个辅助索引:

InnoDB 表是基于聚簇索引建立的。因此InnoDB 的索引能提供一种非常快速的主键查找性能。不过,它的辅助索引(Secondary Index, 也就是非主键索引)也会包含主键列,所以,如果主键定义的比较大,其他索引也将很大。如果想在表上定义 、很多索引,则争取尽量把主键定义得小一些。InnoDB 不会压缩索引。

综上总结:

索引列的数据长度能少则少

索引一定不是越多越好

匹配列前缀可用到索引 like 999%,like %999%用不到索引

where 条件中 not in <>操作无法使用索引

匹配范围值,order by,group by也可用到索引

用指定列查询,少用select *:如果查询列可通过索引节点中的关键字直接返回,则该索引称之为覆盖索引。覆盖所引客减少数据库IO,将随机IO变成顺序IO,可提高查询效率

使用表达式或者函数索引失效

对于过长字符串需要可通过创建前缀索引:前缀的选择要有好的离散性

联合索引如果不是按照索引最左列开始查找,无法用到索引

联合索引中如果查询的某个列的范围性查询,则某右边的所有列都无法使用索引

该博客很多图都是盗图。。。请见谅

本人QQ/wechat:806751350

github地址:https://github.com/linminlm

猜你喜欢

转载自blog.csdn.net/qq_32695789/article/details/85454057