【MySQL学习笔记】高效数据查找结构之B+树索引

数据库我们使用频率最高的,就是数据的查找了,怎么看一个查找的效果好不好呢?那当然是查找速率了,以及空间的占用。即时间和空间两个的复杂度都要低,那才称得上是一个好的数据库。

谈到查找,我们最普通的想法就是遍历,一个一个找下去,把所有的数据都找完了,不就找到了吗,可是这很不 amazing,速度太慢了,数据库中记录一多,查找效率就很慢,那么MySQL是如何解决这个问题的呢?

MySQL中InnoDB数据库引擎通过建立索引来维持高效的查找。

一、MySQL 中记录的存放方式是怎样的?

MySQL中记录是存放到页中的,一个页中有多条记录,页与页之间通过一个双向链表进行连接,每个页的File Header中都有一部分存储上一个页的页号和下一个页的页号,都是占用4字节。

先不要着急记录中的字段结构,下面我们会进行讲解。

二、为什么要建立索引?

谈到这个问题,我们先来了解以下普通的查找思路,正如我们上边所说,就是一个页面一个页面的找呗,好,我们就一个一个找。

没建立索引的痛苦
  • 如果数据很少很少,只有一个页(一个页总共空间是16KB),我们可以选择顺序查找,一条记录一条记录的找,那还有没有更好的方法呢,有,就是二分,但是这是有使用条件的啊,就是如果你是根据主键进行查找时,可以采用二分法快速定位到对应的位置,因为记录是按照主键大小顺序进行存储的,但如果你不是根据主键进行查找的呢,那就么的办法了,只能一个一个的找了呗,可想而知,是多么耗时。
  • 如果数据量很多,这时一个页就不够了,肯定有多个页了,如果还用遍历的方法,这可就难受了,遍历时间复杂度是O(n)。
建立索引的舒服

查找只需要两步。

  • 定位到所在的页
  • 在定位到的页中进行查找

很舒服的是这两步都能通过建立索引把时间复杂度缩短到O(n)以下,是不是很舒服,既然效率高,建立索引,何乐而不为呢。

三、MySQL中的索引

MySQL中的索引主要是B+树索引,当然也有哈希索引,但我们讲的是主要。

什么是索引?

建立索引相当于为数据页编写了一个字典目录,通过目录我们能够很快的查找到页的位置,然后再找到记录的位置。

索引干了个啥事呢?

想一想,我们要想实现二分类似的快速查找,我们得先把页号提取出来吧,索引就是干了个这事,索引通过将页号不断提取出来,最终形成一颗树一样的多层次结构,这种结构就是B+树。

B+树索引

B+树有以下一些规则:

  • 树形结构
  • 有k个子树的中间节点包含有k个元素
  • 非叶子节点不保存数据,所有数据都保存到叶子节点上
  • 叶子节点之间按照关键字的大小自小到大顺序通过链表进行连接
  • 非叶子节点保存其子节点中元素的最大或最小值

根据其规则,我们能够画出MySQL中B+树索引的结构,如下:
在这里插入图片描述

我们来解释以下这棵神奇的树
每个页中最上面那个蓝色的方框是代表啥呢,蓝色方框所指的是上面我们所说的记录结构的record_type字段,其值可以取0,1,2,3。0代表是普通记录,也就是存放实际数据的记录。1表示B+树非叶子节点记录。2表示最小记录,3表示最大记录。

第二个蓝色方框代表啥呢,第二个蓝色方框所指的是记录结构中的next_record字段,其中存放了从当前记录的真实数据到下一条记录的真实数据的地址偏移量。说人话也就是,通过这个我们可以找到下一条记录。

第三个橙色方框中存放的是建立数据表是所设定的主键的值,如果没有指定主键的话,数据库会自动指定主键。

非叶子节点中的绿色方框很明显就是指子节点的页号啊。

剩下的深蓝色和红色方框中存放的就是实际的数据了,当然那个橙色方框中的主键也是数据项。

加索引后的效率

效果怎么样,试试就知道

在这里插入图片描述

又是这个图,我们试一下查找,假如我们要查找主键为220的记录,加上索引后,我们的查找为页33 -> 页30 -> 页9,通过三次我们就找到了所需要记录所存放的页号,之后再在页中进行二分查找就能找到了,是不是很快。相比遍历那种比较笨的方法,效果就非常好了。

聚簇索引与二级索引

上面我们所说的数据存放于叶子节点的就是聚簇索引。

B+树中的数据是按照主键顺序进行排序的,但是如果我们的查找条件并不是按照主键的呢。这时我们的索引就没用了,一个想法就是为每个属性建立一颗B+树,这当然可以,但是太浪费了吧,一份数据存有好几份,这真的是太浪费存储空间了,我们怎么做呢,我们为其他非主键属性建立一个二级索引。

与聚簇索引不同的有以下几点(假如我们根据 c 查找到记录,c 不是主属性):

  • 页内的记录是按照 c 列的大小顺序排成的一个单向链表

  • 存放用户记录的页也是根据页中记录的 c 列大小顺序排成一个双向链表

  • 存放目录项记录的页在同一层次上页与页之间按照 c 列的大小顺序通过双向链表进行连接

  • B树的叶子节点存储的不是完整的用户记录,而是 c 列 + 主键这两个列的值

  • 目录项记录不是主键 + 页号,而是 c 列 + 页号

二级索引的查找过程:

  • 先根据待查找的属性值在二级索引中查找到聚簇索引中对应的主键,然后回表,在聚簇索引中再进行一遍查找,直到找到记录
MyISAM 中索引简单介绍

MyISAM也是用树形结构,但是将索引和数据分开存储。

  • 将表中记录按照记录的插入顺序单独存储在一个文件中,称为数据文件
  • 把索引信息另外存储到一个叫做索引文件的另一个文件中
  • MyISAM 会单独为表的主键创建⼀个索引, 只不过在索引的叶⼦节点中存储的不是完整的⽤户记录, ⽽是主键值 + ⾏号的组合。 也就是先通过索引找到对应的⾏号, 再通过⾏号去找对应的记录 ,这不就是回表操作吗?这不就意味着MyISAM中使用的全是二级索引
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值