Mysql数据库引擎 InnoDB 和 MyISAM 对索引的支持原理

Mysql索引的底层

mysql 索引的底层数据结构主要有两种,一种是通过Hash的方式,另外一种是通过Btree的方式。

Hash

hash表是快速检索数据的有效办法。通过哈希算法,也叫散列算法,把索引列数据变换为固定长度的key地址,然后通过这个地址,找到需要检索的数据。
例如 select * from user where id = 1
通过 hash算法算出 id=1 的映射物理地址,用这个地址找到 id=1 对应的数据。
但是有一种特殊情况,哈希碰撞。比如 id=1 和 id=7 的hash算法算出的物理地址相同,此时为hash碰撞。最常用的解决方式是链地址法,即用链表的方式,将碰撞的数据连接起来,每次检索数据,遍历链表,找到key的位置。
hash索引如果只查找一条数据,速度是非常块的,但是范围索引通过hash查找显然不是一个好的办法。

二叉查找树

在这里插入图片描述

如图是一个二叉查找树,所有数据都是有序的,左边的节点,一定小于右边的几点。
如果要查询 11 这个节点的数据,只需要查三次,第一次和 根节点9 比较,11>9 查右边的节点,在和 22 比较,11<22 查左边的节点,找到左边节点 11。
如果是范围查找,也能很好的支持比如 查找大于9的数据,只需要查找一次,和根节点 9 比较,大于9的数据在节点右边,然后遍历所有的节点。
但是二叉查找树有一个缺点,如果 添加的数据依次是 1,2,3,4,5
在这里插入图片描述
如果所示,树结构变成了链表结构,查询数据需要遍历链表。严重影响了查询效率。

平衡二叉搜索树

平衡二叉搜索树又叫 avl树,从之前介绍我们知道,二叉查找树在极端情况会成为一个链表,avl树解决了这个问题。
avl树有一个重要的特性,就是左右两边的子节点高度绝对值不超过1。为了满足这个条件,avl实现了自旋转。
在这里插入图片描述
如图,同样是添加数据依次是 1,2,3,4,5,二叉查找树是链表的样子,avl树,通过旋转还保持树的结构。
想了解avl树自旋转请移步 https://blog.csdn.net/qq_25343557/article/details/89110319
不难看出,avl树的查询小略是比较高的,但是为了让树左右两边的子节点高度绝对值不超过1,更新操作可能会涉及很多的旋转操作,这都是会影响性能的。

红黑树

红黑树相当于avl树的一个变种树,avl树严格保证树的平衡性,即左右子树高度绝对值不大于1。而红黑树只是追求左右子树的大致平衡。放弃绝对平衡的好处就是旋转的次数是可控的,而avl树每次更新,旋转次数是个未知数。所以红黑树的统计性能相对与avl树会高一些。
红黑树和avl树也是有不错的查找效率的,但是用做索引是有弊端的。
首先avl树的频繁自旋,这本身就是一个非常影响性能的。其次数据库的数据可能会有百万千万条数据,如果索引用的是红黑树或者avl树,那树的深度会非常大,查询时,一级一级的向下遍历,对查找而言是非常耗费性能的,数据库不可能忍受这种无意义的等待,而且每个节点代表一个数据,这样向下遍历,是非常庞大的io操作,这可能会有性能瓶颈。

想了解红黑树请移步https://www.jianshu.com/p/e136ec79235c

B-tree

B-tree 又叫 B-树,又叫B树。
在这里插入图片描述
如图是一个B树,B树是从红黑树演变来的。不同的是B树的每个节点横向都可以存放多个数值,数值从左到右越来越大,并且同一个数值只会在一个节点中。同样是一千万数据,B树的深度肯定是要小于红黑树的。节点中数值的个数是可以设置的。默认最大是16KB的数据。如果数据太多太大是没有意义的,既浪费内存,又浪费加载时间。
以根节点为例,【0033,0073】 其实节点存储的除了数值还有一个指针,指向了在磁盘文件中的位置。 0033 的前面有个指针 指向了小于33的数据在磁盘中的位置,后面存放的是大于等于33,小于73的指针。
查找数据时,根节点默认是在内存中进行的,比如要找55,第一次在根节点找55,55>=33并且55<73,所以找到了33和73中间的磁盘指针,将这些数据加载到内存,55个53进行比较,找到了53后面存放的指针,在将磁盘文件加载到内存,找到55。每次操作都是在内存中进行。
使用B树进行查找关键字,可能直接在根节点就找了想要获取的数据,也可能一直到叶子节点才找到。查询效率不稳定。
MongoDB的底层用的B树。

B+tree

B+树是B树的变种树,也是数据库索引所用到的树。B树的关键字分布在不同的节点中,并且只会出现一次。而B+树的根节点存放的都是索引数据,所有的数据都在叶子节点中存放。
在这里插入图片描述
如图是一个B+树,根节点(最后一排上面的都是根节点)存放的都是索引字段。
比如查检索关键字22,从根节点找到22,22=22,如果是B树,此时可以直接返回了。但是B+树根节点存放的都是索引需要一直找到叶子节点,所以需要继续向下找。22>=22,找到右边的子树,【43,54】22小于43,所以在向下找,找到左边的子树,此时到了叶子节点,找到了关键字22。
叶子节点中,关键字的下面其实还存放着数据的所在磁盘文件指针,或者数据(根据mysql索引引擎的不同,存放的不同)。
图中,每个叶子节点中都有一个箭头,它的做用其实是用来范围查找的。直接向左或向右查找叶子节点就可以了,不用像其他树,返回当根节点从新比较,遍历。

Innodb 引擎

在这里插入图片描述
打开本地mysql所在文件,会有一个data目录,其中存放的是所有的数据库目录,点开就是我们所创建的表。
找到一个Innodb 引擎 的表,我们发现有这样的两个文件,frm存放的是表结构,idb存放的是数据和索引。
以 select * from user where id =10 为例,因为idb存放的是数据和索引,所以直接在idb文件找数据就可以了。
此文件存放的索引是以B+树形式存放的,找到索引,除了索引还存放了数据(Myisam 引擎存放的不是数据,是指针)。
注意:只有主键索引处才会存放数据,非主键的索引存放的是主键索引。索引用非主键索引查需要先找到主键,在用主键找数据。

Myisam 引擎的实现

在这里插入图片描述
Myisam引擎的数据表,是这样三个文件存放的,frm存放的是表结构,MYD存放的是数据,MYI存放的是索引。
同样以 select * from user where id =10 为例,首先去MYI文件中找到索引,此文件就是B+树结构,找到索引拿到磁盘文件指针,就可以在MYD文件中找到需要的数据了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值