看了还不懂b+tree的本质就来打我
看了还不懂b+tree的本质就来打我
大家好,我是蓝胖子。
今天我们来看看b+tree这种数据结构,我们知道数据库的索引就是由b+tree实现,那么这种结构究竟为什么适合磁盘呢,它又有哪些缺点呢?
我将不会对b+tree的一些定义做过多的讲解,因为这些东西网上一大推,关键还是要抓住本质,想想为什么b+tree这么设计 ?
b+tree,磁盘,文件系统之间的关系
要想理解b+tree的本质,一定要理解如何在磁盘上高效的存取数据。先看下磁盘是如何读取数据的。
来看下磁盘的结构图。

这是磁盘的一个柱面,读数据的时候,就是磁头来回左右的移动。柱面中一圈圈的叫做磁道,每个磁道都被切分为一个个扇区,磁盘读取的单位就是一个扇区一个扇区的读取。而如果要读取的数据在不同的磁道,就需要磁头前后移动到达指定磁道后再移动到特定扇区进行读取,而磁道的变换就是磁盘读取最耗时的过程。
所以对于磁盘怎样加速读取呢?
终极目的要尽量减少存取时不同磁道间的切换,如何减少切换开销?也很简单,往磁盘写入数据时尽可能在同一个磁道上写,从读取读取数据时,也保证尽可能在同一个磁道上读。
但平时我们并不直接操作磁盘,而是通过文件系统往磁盘上写入和读取数据,文件系统每次读取是按块为单位,一个块往往是多个连续的扇区构成。注意连续的扇区是为了减少磁道切换的开销。

从磁盘上找文件需要找到文件inode数据块,再从inode数据块中找到文件具体的数据块置,可以简单把一个文件理解为一个个文件块构成的,如图每个块都有自己的编号,这里的编号是连续的,实际上,分配的文件块编号也可以不连续。
那么文件系统和b+tree的关系是什么呢?
数据库也是通过文件系统去读取磁盘上的数据的,而数据库中读取数据的单位是一页,不过这个一页数据大小是文件块的整数倍(例如mysql数据页是16kb,而一般操作系统是4kb)。并且数据库实现索引时,会让b+tree中一个节点的大小刚好占用一页数据的大小。
这里其实又会产生一个疑问?如果大小是文件块的整数倍,那么一个btree节点的所占的空间也就是数据库一个数据页所占的空间 在磁盘上一定是连续的吗,答案为 近乎是连续的,因为文件系统在一次性分配文件块时,为了提升文件系统的性能,即减少磁道的变化,会倾向于连续分配。
比如我们告诉操作系统,往一个文件里写入16kb的数据,那么操作系统为文件分配的这16kb的数据会倾向于由4个连续的文件块构成。
这里还需要特别注意的是,比如文件块1,2,3,4 四个文件块 组成b+tree的根节点,那么b+tree的子节点一定是图中的文件块5,6,7,8组成的吗?
实际上也不是 ,因为随着b+tree节点的删除,分裂等操作,由1,2,3,4文件块组成的根节点 指向的子节点位置可能已经变成了其他连续的文件块组成的节点了,它们之间是逻辑上的相邻,在物理磁盘上并不相邻。
举个例子:
为了简单起见,我还是假设数据库在实现的时候,将一个b+tree的节点大小和文件块大小设计为相等。
比如文件块1的节点的左孩子指向了文件块2的节点,如果文件块2的节点中的数据被全部删除了,那么文件块2整个空间就会被标记为删除状态。而文件块1的节点的左孩子指针将会指向其他的文件块,空出来的文件块2的空间则会被新的节点拿来存放数据。可以看到,父子节点之间,只是通过指针联系在了一起,而父子节点可能处于相隔很远的文件块上。
理解了b+tree节点和文件块和磁盘扇区三者关系后,我们再来实际看看b+tree的写入过程,同时便能理解为什么b+tree的写入性能不高了。
b+tree的写入过程
真实数据库的b+tree一个节点能容纳上千个key,为了简单的演示下b+tree的写入过程,这里我会用一个最简单的b+tree来做演示。最简单的b+tree实际上是一颗2-3树。
它具有的特性是每个节点最多能容纳两个元素,孩子节点最多是3个。注意b+tree的插入都是往叶子节点插入。

拿最后一个插入元素4举例,首先得从整颗b+tree中找到4应该插入的节点位置,读取节点内容后,发现 最后一个叶子节点如果加上元素4,将会破坏2-3树的性质,所以又会产生节点的分裂,其父节点的内容也会发生变化。
由于b+tree各个节点之间在物理磁盘上可能已经跨越了不同的磁道了, 所以无论从插入时必须 首先得找到节点这个过程来看,还是分裂时会改变父节点这个过程来看,这样的过程都可以认为是随机读写磁盘的行为,都可能跨越多个磁道。而跨越多个磁道的操作,是磁盘最耗时的操作,这样的插入性能当然不高。
后续我也会介绍另一种构建索引的数据结构LSM(日志结构合并树),有别与b+tree,它具有很好的写入性能。
看了还不懂b+tree的本质就来打我的更多相关文章
- 深度分析:面试阿里,字节跳动,美团90%被问到的List集合,看完还不懂算我输
1 List集合 1.1 List概述 在Collection中,List集合是有序的,可对其中每个元素的插入位置进行精确地控制,可以通过索引来访问元素,遍历元素. 在List集合中,我们常用到Arr ...
- 详细!Mybatis-plus常用API全套教程,我就不信你看完还不懂!
前言 官网:Mybatis-plus官方文档 简化 MyBatis ! 创建数据库 数据库名为mybatis_plus 创建表 创建user表 DROP TABLE IF EXISTS user; C ...
- webpack代码分离 ensure 看了还不懂,你打我(转)
webpack异步加载的原理 webpack ensure相信大家都听过.有人称它为异步加载,也有人说做代码切割,那这 个家伙到底是用来干嘛的?其实说白了,它就是把js模块给独立导出一个.js文件的, ...
- 看完此文还不懂NB-IoT,你就过来掐死我吧...【转】
转自:https://www.cnblogs.com/pangguoming/p/9755916.html 看完此文还不懂NB-IoT,你就过来掐死我吧....... 1 1G-2G-3G-4G-5G ...
- 看完此文还不懂NB-IoT,你就过来掐死我吧...
看完此文还不懂NB-IoT,你就过来掐死我吧....... 1 1G-2G-3G-4G-5G 不解释,看图,看看NB-IoT在哪里? 2 NB-IoT标准化历程 3GPP NB-IoT的标准化始于20 ...
- Java的BIO和NIO很难懂?用代码实践给你看,再不懂我转行!
本文原题“从实践角度重新理解BIO和NIO”,原文由Object分享,为了更好的内容表现力,收录时有改动. 1.引言 这段时间自己在看一些Java中BIO和NIO之类的东西,也看了很多博客,发现各种关 ...
- 盘点国内程序员不常用的热门iOS第三方库:看完,还敢自称”精通iOS开发”吗?【转载】
综合github上各个项目的关注度与具体使用情况,涵盖功能,UI,数据库,自动化测试,编程工具等类型,看完,还敢自称”精通iOS开发”吗? https://github.com/syedhali/EZ ...
- 我看谁还说程序员不会P图?拜托~4行python代码就够~
我们平时使用一些图像处理软件时,经常会看到其对图像的亮度.对比度.色度或者锐度进行调整.你是不是觉得这种技术的底层实现很高大上? 其实最基础的实现原理,用 Python 实现只需要几行代码,学会后你也 ...
- 一篇文章看懂JS闭包,都要2020年了,你怎么能还不懂闭包?
壹 ❀ 引 我觉得每一位JavaScript工作者都无法避免与闭包打交道,就算在实际开发中不使用但面试中被问及也是常态了.就我而言对于闭包的理解仅止步于一些概念,看到相关代码我知道这是个闭包,但闭包 ...
- 看完这篇还不懂Redis的RDB持久化,你们来打我!
一.为什么需要持久化 redis里有10gb数据,突然停电或者意外宕机了,再启动的时候10gb都没了?!所以需要持久化,宕机后再通过持久化文件将数据恢复. 二.优缺点 1.rdb文件 rdb文件都是二 ...
随机推荐
- mac SIP系统完整性保护关闭方法
许多Mac用户反应,装了部分软件后打不开,那可能是sip系统完整性没有关闭.下面我们就来看一下如何关闭sip系统完整性. 检查状态 在sip系统完整性关闭前,我们先检查是否启用了SIP系统完整性保护. ...
- Java+selenium自动爬取网站内容并写入本地
目的:本文主要描述如何使用Java+selenium爬取58同城招聘页,并记录指定职位的招聘公司名保存到本地 一.首先创建一个maven工程,配置依赖包 1 <dependencies> ...
- scala调用fastjson JSON.toJSONString()序列化对象出错
在scala中需要将case class 序列化为string,代码如下 results.map(JSON.toJSONString(_)).foreach(println) case class p ...
- 数据库tempdb的事物日志已满,原因为“ACTIVE_TRANSACTION”
系统运行过程中,突然报错数据库tempdb的事物日志已满,原因为"ACTIVE_TRANSACTION".导致所有业务崩溃. 接到报警后,进入数据库服务器.检查硬盘空间正常,于是登 ...
- 物联网之Wifi协议
今天来重点介绍一下WIfi协议,咱们用的其实已经很多了. 主要内容: ⼀.基本概述 ⼆.实践基础 三.⼀些原理 ⼀.基本概述 ============================ 1.有线和⽆线⽹ ...
- ie8 不支持 trim方法
那就自己写一个trim() String.prototype.trim = function() { return this.replace(/(^\s*)|(\s* ...
- 视觉里程计1-SLAMCP7
--20.11.27 在CP2里面讲到,视觉SLAM主要分为视觉前端以及优化后端,后端也被称为视觉里程计(VO).根据相邻图像的信息,估计粗略的相机运动,给后端提供较好的初始值.VO的实现方法按是否需 ...
- 天龙八部<三联版>三
虚竹经历这么多事情,只想回少林寺,在面馆遇到出来玩的阿紫被阿紫调戏而破了荤戒.随后丁春秋到来,抓到阿紫,恰好慕容复也来到面馆,二人相斗,阿紫在打斗过程中被丁春秋刺瞎双眼,但却被游坦之救走, 最后慕容复 ...
- 20192305 王梓全Python程序设计实验三报告
20192305 王梓全Python程序设计实验三报告 课程:<Python程序设计> 班级: 1923 姓名: 王梓全 学号:20192305 实验教师:王志强 实验日期:2021年5月 ...
- not eligible for getting processed by all BeanPostProcessors
描述 这个BUG大的起源是我上线以后,在后台看日志的时候发现一行奇怪的INFO日志: 2022-06-09 23:34:24 [restartedMain] [org.springframework. ...