Mysql(9)——B-树索引详解

索引的底层实现原理

数据库索引是存储在磁盘上的;
当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘块(对应索引树的节点),索引树越低;

越“矮胖”——>磁盘IO次数就少
xxx有索引==》 存储引擎==》kernel==》磁盘IO(读索引文件)==》内存上

MySQL支持两种索引:

  • B-树索引
  • 哈希索引

大家知道,B-树和哈希表在数据查询时的效率是非常高的。

这里我们主要讨论一下MySQL InnoDB存储引擎,基于B-树(但实际上MySQL采用的是B+树结构)的索引结构。

B-树是一种m阶平衡树,叶子节点都在同一层,由于每一个节点存储的数据量比较大,索引整个B-树的层数是非常低的,基本上不超过三层。

  • 题外话:内存是按page页面(4k为单位)操作的,当我们向操作系统申请4byte时,实际上内核按照页面给我们分配,在这之后,假设返回了两个页面即2x4k = 8k,应用程序只需要4个,剩下的就被c库(libc.so或者libc++.so)的malloc实现ptmalloc或者tcmalloc来管理。这两个函数(或者说缓存用来管理多余的空间),这样做的好处就是该应用程序下一次malloc或者new时,就不要陷入kernal内核空间去申请内存,下次直接在用户空间中使用,效率更高。
  • 由于磁盘的读取也是按block块操作(一般是16k,也是内存页面的整数倍) ,因此B-树的节点大小一般设置为和磁盘块大小一致,这样一个B-树节点,就可以通过一次磁盘I/O把一个磁盘块的数据全部存储下来,所以当使用B-树存储索引的时候,磁盘I/O的操作次数是最少的(MySQL的读写效率,主要集中在磁盘I/O上)。

上面的内容可能不好理解,我们通过一个示例理解一下:假设我们有2000w的数据:

  • 使用AVL树存储,构建下来有log220000000 ≈ 25层,最坏情况下读取一个索引要花费25次磁盘IO
  • 使用B树存储,m阶平衡树(m一般取300-500),假设m= 500,log1020000000 / log10500≈ 3层,这种情况下最多花费三次磁盘IO

在这里插入图片描述

建立索引的过程如下:

  1. 当执行select语句时发现,where条件列uid是已经建立好索引的;
  2. 于是请求存储引擎,请求内核;
  3. 磁盘IO读取索引文件,读取到内存上;
  4. 用读取到的数据构建B树,从而加速搜索。

注意:这里的data是存储的是数据本身的内容,还是数据在磁盘上的地址呢?
——这与存储引擎相关,

  • 如果是MYISAM,索引和数据是分开存储的(想想之前学过的内容),构建的索引树,一定是数据的地址;
  • 要是用InnoDB,数据跟索引一起存放,索引树上放的是数据

注意:如果在InnoDB存储引擎下,where后的字段名没有建立索引,但是由于InnoDB存储引擎会自动建立索引,但是搜索条件并未和索引列建立关系,那么我们就会遍历整个索引树,也就相当于整表搜索。

根根据B树的结构特点(排序关系),最终采取的搜索策略是二分搜索,时间复杂度是(O(log2n)),那么如果我们使用AVL树,不同样也是(O(log2n))吗?

搜索的过程分为两步:

  1. 花费磁盘IO把数据构建到内存的索引树上
  2. 再在索引树上搜索数据

即便搜索这个过程的时间是一样的,但B树的好处就是非常少的磁盘IO,在这方面提升了效率,这在之前我们已经提及了。

从上图可以看到B-树存在的缺点:

  • 每个节点中有key,也有data,但是每一个节点的存储空间是有限的,如果data数据较大时会导致每个节点能存储的key的数据很小
  • 当存储的数据量很大时同样会导致B-树的高度较大,磁盘IO次数花费增大,效率降低
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值