MSQL系列(二) Mysql实战-索引结构B+Tree

news2024/11/25 2:26:04

Mysql实战-索引结构 B+Tree

上一篇 我们讲解了二叉树,平衡二叉树,红黑树,BTree的结构及特点,本文我们着重讲解一下B+Tree,为什么Mysql的存储结构采用B+Tree而不是上面的那几种

1.BTree的缺点

我们用上篇文章中的BTree的例子
image.png

想要访问定位60元素,要访问3次磁盘空间,由此可知,BTree查找效率与树的高度有密切的关系

  • 当数据量大时,树的高度也很高
  • 树的高度高,就导致读取磁盘IO很频繁,效率就很低下
  • 当系统从磁盘读取数据到内存时是以磁盘块作为读取数据的基本单位
  • 位于同一个磁盘块中的数据会被一次性读取出来,而不是需要什么取什么
  • InnoDB存储引擎中有页(Page)的概念,页是其磁盘管理的最小单位
  • 也就是说一次磁盘IO,就会读取一页的数据
  • InnoDB在把磁盘数据读入到磁盘时会以页为基本单位,在查询数据时如果一个页中的每条数据都能有助于定位数据记录的位置
  • InnoDB存储引擎中默认每个页的大小为16KB
  • 参数innodb_page_size可以设置页Page的大小设置为4K、8K、16K
  • 一个页的存储空间是有限的,如果data数据较大时将会导致一页能存储的key的数量大幅减小
  • Key数量少,就会导致节点多,节点多 就会导致B-Tree的深度较大,高度高
  • 高度高,查询时的磁盘I/O次数就多,查询效率就低

我们可以使用 命令,查看MySQL配置的页的大小:

mysql> show variables like 'innodb_page_size';

image.png

那么如何把瘦高的BTree 变为 矮胖的 树,方便查找呢?

2.B+Tree的原理

InnoDB存储引擎就是用B+Tree实现其索引结构,B+Tree是在BTree树上的一种优化,为的就是使BTree 更加的 矮胖(高度低, 且 叶子节点多), 使其更适合现在存储索引结构

image.png

在B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+Tree的高度。

对比上面的BTree和B+Tree,我们可以很清晰的看到, 56/56/77 这三个元素下面是没有data数据的,中间元素不保存数据,只用来做索引,所有的数据全都保存在叶子节点,B+Tree有以下特点

  1. 非叶子节点只存储键值Key信息,因为没有data,一页可以存储很多Key
  2. 数据记录都存放在叶子节点中, 15/18/20/30 全都是叶子节点,叶子节点才有data数据
  3. 所有叶子节点之间都有一个链指针,底层15/18到20/30 节点中间有一个指针,按顺序指引
  4. 所有叶子节点形成有序链表,便于范围查询

原来的BTree 现在用B+Tree来展示,如图所示
image.png

3.B+Tree的树层级高度低,叶子节点多

B+Tree 的数据全部保存在末端的叶子节点中,这样有什么好处?

  • 每页非叶子节点能够保存的索引Key值就会就很多,降低了树的高度了,树变矮了
  • 这种存储导致末端的叶子节点的数量非常庞大,增大树的宽度, 树变胖了
  • B+Tree保存2000多万条数据时,B+Tree 只要 3 层
  • BTree 则需要至少 6 层 才能满足

BTree 的叶子节点之间没有双向指针,不能很好地支持范围查找

B+Tree 叶子节点之间有双向指针,从左到右的索引值是从小到大的顺序排序,可以高效支持范围的查找

4.为什么使B+Tree做索引,而不是红黑树

为什么用B/B+树这种结构来实现索引呢? 而不是用红黑树做索引呢 ?

我们先从红黑树的特点来解释

  • 红黑树使存储在内存中才会使用的数据结构
  • 在大规模存储数据的时候,红黑树不允许相邻父子红/红,黑/黑,这种难免会增加树的深度
  • 树的深度过大,读取数据就会造成磁盘IO读写过于频繁
  • 磁盘查找读取的次数往往由树的高度所决定,
  • 高度高,读取次数多,IO读取效率低下,从而导致查询效率低下

所以,我们要把树变的 矮胖,设置树结构时尽量减少树的高度

5.B+Tree预读

为了提升效率,要尽量减少磁盘IO的次数。实际过程中,磁盘不是每次严格按照页的大小来读取,而是每次都会预读

磁盘读取完本次需要的数据后,根据局部性原理,一个数据被使用,它的相邻数据可能马上也会被使用,程序需要的数据可能比较集中, 这样磁盘读取会按顺序再多读一部分数据到内存中,避免频繁的磁盘IO读取

  • 由于磁盘顺序读取的效率比寻道时间高,所以会预读,采用预读可以提高I/O效率
  • 预读的长度一般为页(page)的整倍数。
  • MySQL(默认使用InnoDB引擎),将数据记录按照页的方式进行管理
  • 系统参数innodb_page_size可以设置每页Page的大小设置为4K

至此 我们讲解完了BTree和B+Tree的对比,并且分析了B+Tree为什么能够打败红黑树和BTree,成为Mysql御用的索引存储结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/534803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第四十二天学习记录:C语言进阶:笔试题整理Ⅲ

问:解释一下int(*a[20])(int)是什么? ChatAI答: int (*a[20])(int) 是一个数组,该数组中每个元素都是一个指向函数的指针,该函数具有一个int类型的参数,并返回一个int类型的值。 具体来说,a是一…

宝塔服务器(linux)服务器搭建

搭建服务器 nginx 搭配 PM2( 集合了node的功能 ) 搭建服务器 域名: http://kissface.top 流程如下: 服务器既做assets文件目录挂载 , 也当做nodejs服务使用 当我访问http://kissface.top 根目录时 展示index.html文件 同时能访问静态资源如 js/css/img/font 等 当我访问 http…

Linux:初识【VI / VIM编辑器】

Linux系统版本:centos 7.5 x64位 VMware版本: VMware Workstation Pro 16 文章目录 一、VI / VIM是什么?1.1 VI编辑器1.2 VIM编辑器 二、为什么要使用VI / VIM编辑器?三、如何使用VI / VIM编辑器?3.1 一般模式3.2 编辑…

keil MDK5插件推荐——Astyle代码格式化插件

前言 代码格式化是提高代码质量和可读性的重要手段之一。然而,在Keil MDK5中并没有内置代码格式化工具,因此需要寻找第三方工具来解决这个问题。开源的代码格式化工具Astyle能以插件的形式集成到Keil中以满足我们对代码格式化的需求。 本文将详细介绍如…

《永恒之塔sf私服》“龙战前传”里的更高挑战-

关于这个新版本的各种更新内容已经屡见不新,无论是最新关注的玩家,抑或是一直坚守在永恒之塔阵地的老玩家们,相信已经对各种感兴趣的更新倒背如流。这里就不再重复。 每一款MMO游戏升级,伴随着玩家技术和战术的长进,游…

【Unity-UGUI控件全面解析】| ScrollView 滚动视图组件详解

🎬【Unity-UGUI控件全面解析】| ScrollView 滚动视图组件详解一、组件介绍二、组件属性面板三、代码操作组件四、组件常用方法示例💯总结🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉 🎄 学习专栏推荐:Unity系统学习…

火线、零线和地线及开关接线参考

火线、零线和地线及开关接线参考 1. 火线、零线和地线 1.1. What is Live wire? Live wire,L:火线,相线火线是电路中输送电的电源线。 1.2. What is Neutral wire? Neutral wire,N:零线零线是由发电机或变压器二…

AD 实现多 DC + 多 ADFS 高可用部署

总览 在本篇文章中, 我将记录部署多 DC 多 ADFS 实现高可用方案的详细步骤, 期间我会尽量使用 PowerShell 来实现相应的动作, 实在找不到命令或者 GUI 更方便的再附截图. 主要步骤分为: 部署 2 台 DC 服务器提供 AD 服务 (AD域名 alian.com)安装 ADCS 角色为 ADFS 提供证书服…

NodeJs模块化之下半部分

Node.js 中的模块化 更多精彩内容,请微信搜索“前端爱好者“, 戳我 查看 。 官网地址:https://nodejs.cn/api/ fs 文件系统 地址:https://nodejs.cn/api/fs.html#%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F node:fs 模块能够以标准…

GPT-3 面试题

简介 1、GPT-3 是什么?它是基于什么模型的? GPT-3是一种基于深度学习原理的语言预测模型。它是由OpenAI开发的,可以从互联网数据中生成任何类型的文本。它只需要一小段文本作为输入,就可以生成大量的准确和复杂的机器生成文本⁴…

Akura Medica:新型静脉血栓切除系统,完成首次人体试验

Akura Medical公司宣布,其机械血栓切除平台在人体首次使用成功,这是一项具有突破性的技术,可以有效地治疗肺栓塞、深静脉血栓等血栓栓塞疾病。该平台使用了一种与众不同的方法,可以高效地清除血管内的血栓,同时保护血管…

测试分词工具Lucene.Net.Analysis.PanGu(盘古分词)

从微信公众号及百度文章来看,全文检索的前置工作是分词,首先将要做全文检索的内容分词,然后采用全文检索模块或工具进行全文检索。参考文献4介绍了基于Lucene.net实现全文检索的大致思路,其采用的是Lucene.net盘古分词的方式实现。…

蓝桥:前端开发笔面必刷题——Day1 数组(一)

文章目录 📋前言🎯数组中重复的数字📚题目内容✅解答 🎯两数之和📚题目内容✅解答 🎯替换空格📚题目内容✅解答 🎯二维数组中的查找📚题目内容✅解答 📝最后 …

C语言-程序环境与预处理

程序环境与预处理 程序环境翻译环境(编译链接)预编译编译汇编链接 执行环境 预处理预定义符#define定义的标识符 宏#define定义宏#define替换规则宏的命名约定带副作用的宏参数宏和函数的比较 其它#和##的使用字符串常量化运算符#标记粘贴运算符## 命令行…

fastled教程

文章目录 EVERY_N_MILLISECONDS(10)EVERY_N_SECONDS(5)fill_solid(leds, NUM_LEDS, CRGB::Red);fill_gradient_RGBfill_rainbow(leds, NUM_LEDS, i, 255 / NUM_LEDS);效果1fadeToBlackBy(leds, NUM_LEDS, 1); 效果2FastLED.setBrightness(2*i);// 效果3leds[i] CHSV(hue (i *…

scanf和scanf_s的区别、解决VS返回值被忽略的报错问题

一、scanf和scanf_s是什么? scanf()不会检查输入边界,可能造成数据溢出。 scanf_s()会进行边界检查。 二、分别分析 1.scanf scanf表示从键盘输入指定格式的数据。如:scanf("%d",x);指从键盘给x输入一个int型(整型&…

【计网】【TCP】浅析TCP三次握手

前言 之前学习计网时不认真,TCP三次握手稀里糊涂就过去了,最近在重新查漏补缺计网这方面的知识,饭要一口一口吃,我就没有把其中涉及到的大量知识点写在此博客中,此文仅管中窥豹,之后再详细写吧。 笔记中有…

初步认识性能测试和完成一次完整的性能测试

上一篇博文主要通过两个例子让测试新手了解一下测试思想,和在做测试之前应该了解人几点,那么我们在如何完成一次完整的性能测试呢? 测试报告是一次完整性能测试的体现,所以,这里我给出一个完整的性能测试报告&#xff…

搞懂@DateTimeFormat 注解 和 对应的时间类型

通常而言,前端时间控件,一般情况下直接会传一个yyyy-MM-dd的日期字符串到后台。如果我们直接用java.util.Date类型来接收,是无法获取的。这是因为Date类型默认的格式为:Tue May 16 00:00:00 CST 2023这种。 举例 ApiOperation(val…

Games104现代游戏引擎学习笔记08

渲染那部分看的云里雾里的,等学完其他图形学的内容再回头开吧 游戏动画的三个挑战: 1.根据交互实时的反应各种变化 2.一帧时间里的庞大计算 3.更真实自然的表现 2D动画 sprite animation 把每一帧精灵循环绘制出来 2D技术实现3D效果 在各个视角采了一…