看了还不懂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文件都是二 ...
随机推荐
- 《CSOL大灾变》Mobile开发进度记录——武器购买界面设计
又到了休息日,有点时间继续这个移植游戏的开发.这次主要是关于武器系统模块的开发记录,关于CS以及CSOL的武器系统,它的购买菜单页面虽然谈不上复杂,但是也包含很多GUI元素,下面是CSOL其中的一个武 ...
- CIC滤波器
CIC滤波器是滑动平均滤波器的非常高效的迭代实现,只需要一个减法和一个加法,而滑动平均需要N-1个加法. cic滤波器相当于一个梳状滤波器y(n)=x(n)-x(n-D),H(z)=1-z-D,和一个 ...
- Surface Pro (1796),安装Win11之后出现的问题。
2020年年中我为了体验微软新的操作系统,加入了Review计划,即:Windows预览体验计划.然后升级到了Win11.由于苏菲一直是作为辅助设备用,所以平时就是开节电模式,中途也升级了几次Win1 ...
- oracle 实例无法启动和初始化
1 先看oracle的监听和oracle的服务是否都启动了.启动oracle监听:cmd的命令行窗口下,输入lsnrctl start,回车即启动监听.2 查看oracle的sid叫什么,比如创建数据 ...
- vue 添加多条数据 添加日期
效果图添加多条数据,日期是具体到天. 后端数据格式time:[ { s_time:' ' , e_time: ' ' }] <p v-for="(item,index) in form ...
- #Python #微信 #消息防撤回 Python实现微信防撤回
微信(WeChat)是腾讯公司于2011年1月21日推出的一款社交软件,8年时间微信做到日活10亿,日消息量450亿.在此期间微信也推出了不少的功能如:"摇一摇"."漂流 ...
- Long类型转换为IP String
package com.barry.iputil.util; public class IPFormat { public static String toIPStr(Long LongIP) { i ...
- Spring-IoC中Set和构造器注入
新建Maven工程 修改pom文件 1 <?xml version="1.0" encoding="UTF-8"?> 2 <project x ...
- 2020ccpc威海C.Rencontre题解(树形dp)
题目大意:给定一棵带边权树,给三份点的集合U1,U2,U3,求0.5*(E(dis(u1,u2))+E(dis(u1,u3))+E(dis(u2,u3))). 即,我们需要维护两份点的所有距离和.显然 ...
- String 练习题
题目一:获取指定字符串中,大写字母.小写字母.数字的个数. 题目二:将字符串中,第一个字母转换成大写,其他字母转换成小写,并打印改变后的字符串. 题目三:查询大字符串中,出现指定小字符串的次数.如&q ...