MySQL采用B+树作为索引的原因

2023-11-10

MySQL采用B+树作为索引的原因

1、MySQL的索引结构是如何查询的

在MySQL中,存储的数据记录都是持久化到磁盘中的,数据包含索引和记录,当MySQL查询数据时,由于索引也是持久化在磁盘上面的,首先会从磁盘上读取索引到缓存中,然后再通过索引从磁盘上面检索数据读取待内存中,在这期间会进去内存与磁盘之间的IO交互,而磁盘IO次数越多的话,所消耗的时间就会从多,所以当从磁盘检索的IO次数越少时,查询速率就会越快,而MySQL是可以范围查询的,所以MySQL索引的数据结构选取就会减少IO次数,并能支持范围查找

2、二叉查找树

二叉查找树是一种经典的数据结构,在二叉查找树中,左子树的键值总是小于根的键值,右子树的键值总是大于根的键值,因此可以通过中序遍历来查询键值的顺序输出,二叉树节点中存储了键(key)和数据(data),如下图所示,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6yuDnKHU-1655435000382)(https://gitee.com/ycodingnow/blogimage/raw/master/image/20220617094702.png)]

对于上图的二叉查找树,当我们需要查找键值为5的记录时,先通过根进行比较,其键值是6,6大于5,接着查询6的左子树,而找到3,5大于3,再找到其右子树,一共进行了3次查找,若如果构造的二叉查找树逐渐退化为链表结构的话, 查询的效率就趋向于链表查询了,故而引出了平衡二叉树,又称之为AVL树

3、平衡二叉树

平衡二叉树定义如下,首先符合二叉查找树的概念,其次必须满足任何节点的两个子树的高度差最大差为1

平衡二叉树保证了树的构造是平衡的,当我们插入或删除数据导致不满足平衡二叉树不平衡时,平衡二叉树会进行调整树上的节点来保持平衡

平衡二叉树相比于二叉查找树来说,查找效率更稳定,总体的查找速度也更快

4、B树

我们知道,在数据库存储时,数据和索引都会存储在磁盘这种外围设备中去,但是和内存相比,磁盘读取的效率会很低下,所以需要尽量避免磁盘IO操作

在进行磁盘读取时,读取数据都是按照磁盘块来进行读取的,并不是一条一条地从数据库进行读取的,而在磁盘中,磁盘读取数据的最小单位为扇区,一个扇区的大小为512B,而操作系统最小读取的块大小为4KB,所以一次磁盘IO会从一次性地读取8个扇区

在二叉查找树和平衡二叉树中,每个节点存储的数据都只是一个键值和对应的数据的,那么实际读取的磁盘块就只会存储一个节点信息,当我们需要读取的数据量非常大时,那么树的高度就会非常高,就会进行多次磁盘IO操作,查询效率就会非常低下

而B树(BaLance Tree),即为平衡树的意思,在B树中,每个节点被称之为页,在MySQL中数据读取的基本单位都是页,B树相对于平衡二叉树,每个节点存储了更多的键值(key)和数据(data),并且每个节点拥有更多的子节点,子节点的个数一般称为阶,高度也会很低

基于这个特性,B树查找数据读取磁盘的次数将会很少,数据的查找效率也会比平衡二叉树高很多

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zyyLivfy-1655435000383)(https://gitee.com/ycodingnow/blogimage/raw/master/image/20220617105855.png)]

5、B+树

B+树和二叉树、平衡二叉树一样,都是经典的数据结构,B+树是由B树和索引顺序访问方法演化而来的,B+树是基于B树的进一步优化而来,与B树相比

  • B+树的非叶子节点是不存储键值,只是存储键值(key),而B树节点不仅存储键值(key)还会存储数据(data),MySQL在使用InnoDB引擎的时候页大小默认是16KB,当页中不存储数据时,存储的键值就会更多,相应的树就会显得’更矮更胖’,这样在进行数据查询时,磁盘IO的次数就会越少
  • B+树的索引数据都是存放在叶子节点的,并且叶子节点是双向链表有序排列的,那么B+树进行范围查找,顺序查找的效率就会更快,而在非叶子节点中,各个页之间都是双向链表进行连接的,

B+树是为磁盘或其他直接存取辅助设备设计的一种平衡查找树,在B+树中,所有记录节点都是按照键值的大小顺序存放在同一层的叶子节点上的,由各叶子节点指针进行连接,先来看一个B+树,其高度为2,每页可以存放4条记录,扇出(fan out)为5,如下图所示

从图中可以看出,所有记录都是存放在叶子节点上的,并且是顺序存放的,如果用户从最左边的叶子节点开始顺序遍历,可以得到所有键值的顺序排序:

5,10,15,20,25,30,50,55,60,65,75,80,85,90

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1PutriAv-1655435000384)(https://gitee.com/ycodingnow/blogimage/raw/master/image/20220617105002.png)]

在数据库中,B+树的高度一般都是在24层,这就是说查找某一键值的行记录时最多只需要2到4次IO,因为当前一般的机器磁盘每秒可以做100次IO,24次的IO意味着查询时间只需要0.02~0.04秒

数据库中的B+树索引可以分为聚集索引(clustered index)和辅助索引(secondary index),但是不管是聚集还是辅助索引,其内部都是B+树的,即高度平衡的

6、聚集索引与辅助索引
  • 聚集索引: 以InnoDB作为存储引擎的表,表中的数据都会有一个主键,InnoDB是把数据存放在B+树的,同时叶子节点存放的即为整张表的行记录数据,也将聚集索引的叶子节点称为数据页,同B+树数据结构一样,每个数据页都通过一个双向链表来进行链接,由于实际的数据页只能按照一棵B+树来进行排序,因此每张表中只能有一个聚集索引,在多数情况下,查询优化器倾向于采用聚集索引,因为聚集索引能够在B+树索引的叶子节点直接找到数据,此外,由于定义了数据的逻辑顺序,聚集索引能够特别快地访问指定范围内的查询,查询优化器能够快速发现某一段范围的数据页需要扫描
  • 非聚集索引:以主键以外的列值作为键值构建的B+树索引,我们称之为非聚集索引,与聚集索引相比,非聚集索引的叶子节点不存储表中的数据,而是存储该列对应的主键,想要查找数据我们还需要根据主键再去聚集索引中进行查找,这个再根据聚集索引查找数据的过程,这种操作称为回表

聚集索引叶子节点存放在所有数据,聚集索引与辅助索引不同的是,叶子节点存放的是否是一整行的信息

在InnoDB中,聚集索引中叶子节点存放的是数据行的所有信息,而在非聚集索引中,叶子节点存放的是该列数据对应的主键,在里面存储了一个书签(bookmark),该书签用来告诉InnoDB存储引擎哪里可以找到与索引相对于的行数,InnoDB存储引擎的辅助索引的书签就是相应行数据的聚集索引键,然后在根据聚集索引去查询数据,在MyISAM存储引擎中,聚集索引和非聚集索引中叶子节点存储的是都是数据的文件地址

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL采用B+树作为索引的原因 的相关文章

  • Mysql 创建定义器

    我创建了一个在 CentOS Web 服务器上运行的 Intranet Web 应用程序 该应用程序使用另一个本地服务器 始终是 CentOS 作为 MySQL 数据库 在数据库内部我创建了例程 这些例程总是这样开始 CREATE DEFI
  • 在服务器上找不到本地主机或 phpMyAdmin:如何修复?

    我按照安装说明进行操作PHP MySQL and PHPMyAdmin 但是当我尝试访问时http localhost phpmyadmin 我收到此错误 未找到 在此找不到请求的 URL phpmyadmin 服务器 然后我尝试访问loc
  • 如何将ElasticSearch与MySQL集成?

    在我的一个项目中 我计划将 ElasticSearch 与 MySQL 结合使用 我已经成功安装ElasticSearch 我可以单独管理ES中的索引 但我不知道如何用 MySQL 实现同样的功能 我读过一些文件 但我有点困惑 没有明确的想
  • MySQL 查询到 CSV [重复]

    这个问题在这里已经有答案了 有没有一种简单的方法来运行MySQL查询来自linux命令行并以csv格式输出结果 这就是我现在正在做的事情 mysql u uid ppwd D dbname lt lt EOQ sed e s g tee l
  • Java JDBC:更改表

    我希望对此表进行以下修改 添加 状态列 varchar 20 日期列 时间戳 我不确定该怎么做 String createTable Create table aircraft aircraftNumber int airLineCompa
  • 一次从多个表中删除行

    我正在尝试将 2 个查询合并为一个这样的查询 result db gt query DELETE FROM menu WHERE name new or die db gt error result db gt query DELETE F
  • 映射 mysql 中同一个表的多个值

    您好 我必须使用另一个表中的值 id 获取文本值 表 1 包含值 ID 表 2 包含名称和值 ID 表 1 SEVERITY OCCURENCE DETECTABILITY 2 3 4 表 2 id name value 1 Very Hi
  • Mysql 时间匹配连接

    我有两个表cpuinfo和jobinfo 我想使用这两种数据创建报告 tabes CREATE TABLE cpuinfo id int 11 NOT NULL AUTO INCREMENT usagetime datetime DEFAU
  • 在mysql中的单个查询中更新多个表

    我有三个查询 我想要一个 这是我的查询 UPDATE tab1 SET a WHERE id 3 UPDATE tab2 SET b WHERE id 9 UPDATE tab3 SET c WHERE id 5 您可以尝试下面的代码 UP
  • 仅当值发生更改时如何插入数据库?

    我需要更新 替换 MySQL 数据库中的字段 但前提是它们已更改 该表包含 ID 文本字段和更改日期 用户根据更改日期通过 ID 查询数据 即 如果该日期早于用户上次查询数据的时间 则他不想要它 仅当文本字段与具有相同 ID 的现有文本字段
  • Galera 集群问题

    我想在我们的生产环境中使用Galera集群 但我有一些顾虑 每个表必须至少定义一个显式主键 每个表必须运行在InnoDB或XtraDB存储引擎下 分批处理您的大额交易 例如 不要让一个事务插入 100 000 行 而是将其分成更小的块 例如
  • MySQL - 从临时表插入

    这看起来非常简单 但我坚持使用简单的插入语句 见下文 begin work CREATE TEMPORARY TABLE IF NOT EXISTS insert table AS select r resource id fr file
  • 连接 Netbeans 和 MySQL 但出现大整数错误

    所以我正在尝试向我的 Netbeans 数据库 即 MySQL 添加新连接 但我遇到了大整数转换错误 有人可以帮助我吗 详细地 我右键单击现有的MySQL 服务器位于 localhost 3306 root 已断开连接 gt gt 选择co
  • MySQL 和 Hibernate 之间的主键自增由谁负责?

    MySQL CREATE TABLE role id role INT 11 unsigned NOT NULL AUTO INCREMENT PRIMARY KEY id role AUTO INCREMENT 1 休眠 Entity p
  • Google Cloud SQL 在重新启动时卡住

    我的云 sql 实例长时间处于重新启动状态 在操作窗格中 重新启动的状态显示为待处理 并且还发生了导出 其状态仍为Running 有没有办法可以强制重新启动或取消重新启动或从常规备份中恢复数据 不 没有办法 如果您向 Google 支付高级
  • PHP 和 MySQL - 高效处理多个一对多关系

    我正在寻求一些有关使用 MySQL 和 PHP 检索和显示数据的最佳方法的建议 我有 3 个表 所有一对多关系如下 Each SCHEDULE有很多覆盖每个覆盖都有很多地点 我想检索这些数据 以便它可以全部显示在单个 PHP 页面上 例如列
  • 无法在 Mac 上启动 MySQL

    使用 Brew 安装后 我无法运行 MySQL 我使用的是 OS X El Capitan 版本 10 11 3 和 MySQL Server 版本 5 7 11 当我启动服务器时 我收到 启动 MySQL 错误 服务器退出而不更新 PID
  • 在 jQuery AJAX 成功中从 MySql 获取特定响应

    好吧 我有这个 ajax 代码 它将在 Success 块中返回 MySql 的结果 ajax type POST url index php success function data alert data My Query sql SE
  • 用 pandas DataFrame 替换 mysql 数据库表中的行

    Python 版本 2 7 6 熊猫版本 0 17 1 MySQLdb 版本 1 2 5 在我的数据库中 PRODUCT 我有一张桌子 XML FEED 表 XML FEED 很大 数百万条记录 我有一个 pandas DataFrame
  • PHP MySql 百分比

    我的问题是关于百分比 我不是专家 所以我会尽力以更好的方式进行解释 我的 mysql 服务器中有一个表 假设有 700 条记录 如下所示 Name country language Birth Lucy UK EN 1980 Mari Ca

随机推荐

  • keil5warning: function “xxxx” declared implicitly的bug分析

    keil5warning function xxxx declared implicitly的bug分析 一 问题分析 可能是头文件出错 自己不小心将两个文件的预编译指令 防止头文件被重复包含 名称写成相同的了 导致想要使用的函数原型声明的
  • Maven和Gradle如何添加依赖

    一 首先来看看Maven项目怎么添加依赖 二 上图中红圈部分的pom xml文件就是可以添加依赖的地方 例如这个 一定要放到 里面
  • 5号字对应的数字字号_字号对照表

    字号 磅数 宋体 黑体 楷体 初号 42 宋体初 黑体初 楷体初 小初 36 宋体小初 黑体小初 楷体小初 一号 26 宋体一号 黑体一号 楷体一号 小一 24 宋体小一 黑体小一 楷体小一 二号 22 宋体二号 黑体二号 楷体二号 小二
  • oracle学习之路(5)Navicat连接Oracle数据库:Oracle library is not loaded 解决方案

    Navicat连接Oracle数据库报错 Oracle library is not loaded 原因 这是因为OCI环境配置有问题 需要修改 oci dll 文件路径 版本不一致 是oci dll版本不对 因为Navicat是通过Ora
  • umi4学习 路由跳转 history useNavigate 的使用

    umi4 history 已经不用query传参了 接下来就来讲讲如何传参吧 第一种 适用于只跳转路径 不携带参数 import history from umi history push user 第二种 用于携带参数 并且参数很多的情况
  • 深度聚类相关(三篇文章)

    一 Deep Clustering for Unsupervised Learning of Visual Features 原文链接 https arxiv org pdf 1807 05520 pdf 完全不需要标签的无监督学习方法 好
  • navicat12,使用自动完成代码,没有默认选中第1个,怎么设置?

    navicat12 使用自动完成代码 没有默认选中第1个 怎么设置 按 TAB 插入第一个选项 ESC 代码提示
  • 【C++】Vector和String详解

    前言 没错 我又更新了 即使没人看 上一篇文章介绍了有关双向链表的容器list 那问题来了 数组和字符串这种使用频率非常高的数据结构 在STL模板中会不会有让人眼前一亮的实现哪 很明显 有 vertor和string就是这两种数据结构相对应
  • Python Flask 中的路由

    Python Flask 中的路由 在 Web 应用中 接口一般都是遵守 RESTful API 设计风格的 这种风格很优雅 而且对用户来说非常易于理解 RESTful API 参考 https blog csdn net weixin 4
  • C语言:电话号码字母排列

    这点B玩意写了一下午加一晚上 但是理解了回溯法也值了 具体解释我写在注释里 include
  • Linux iNode 双网卡,已解决: Zynq 7000 双网卡配置-内核DTS该如何配置 - Community Forums...

    问题 ETH0是通的 ETH1找不到PHY 连接到GMII2RGMII转换器时 找不到该设备 dts和vivado该如何配置 系统 Zynq 7Z015 Vivado 2018 3 内核 4 6 VIVADO工程如下 在内核设备树文件中 配
  • mysql重连次数_Yii2-Mysql重连机制

    背景 nsq消费进程中长时间消费不到数据 mysql设置的自动断开时间超过后 mysql自动断线 服务端报mysql gone away 这时需要捕获异常重连并重试 或者将长连接改为短连接也可以解决该问题 解决 配置项新增 db gt cl
  • python马士兵学习笔记

    前言 本篇文章是作者在B站学习python马士兵视频的笔记 之前章节的内容可参考https blog csdn net qq 43511094 article details 113062435 或https blog csdn net w
  • stat()函数:获取文件状态

    相关函数 fstat lstat chmod chown readlink utime 头文件 include
  • SQL Server 基础操作 (二) 创建用户并且为用户授权

    1 创建用户 右键点击登录名 新建登录名 2 设置管理员权限 进入 服务器角色 在右侧的服务器角色面板中 勾选public 服务器角色 说明 sysadmin 执行SQL Server中的任何操作 serveradmin 配置服务器设置 s
  • nodejs链接mysql报错_nodejs连接数据库报错

    ER NOT SUPPORTED AUTH MODE 报错详情 使用nodejs连接数据库时报错 Error ER NOT SUPPORTED AUTH MODE Client does not support authentication
  • Blockly概述

    原文地址 https developers google com blockly guides overview Blockly是一个用于Web Android IOS的可视化代码编辑器库 Blockly使用了相互关联的积木来表示表达代码中
  • ES 搜索22 (function_score 支持的衰减函数 linear、exp 和 gauss)

    衰减函数 很多变量都可以影响用户对于酒店的选择 像是用户可能希望酒店离市中心近一点 但是如果价格足够便宜 也愿意为了省钱 妥协选择一个更远的住处 如果我们只是使用一个 filter 排除所有市中心方圆 100 米以外的酒店 再用一个filt
  • 关于根轨迹对于控制系统的一点理解

    自动控制理论根轨迹的学习过程中 经常会遇到几个问题 为什么要用根轨迹法 为什么根轨迹法最终转化为调整增益K来反应系统的稳定性和动态性能 为什么根轨迹法用开环传递函数求解的却是闭环极点 盲目的借助于matlab进行根轨迹的计算和绘图 有时候往
  • MySQL采用B+树作为索引的原因

    MySQL采用B 树作为索引的原因 1 MySQL的索引结构是如何查询的 在MySQL中 存储的数据记录都是持久化到磁盘中的 数据包含索引和记录 当MySQL查询数据时 由于索引也是持久化在磁盘上面的 首先会从磁盘上读取索引到缓存中 然后再