是什么影响了 MySQL 索引 B + 树的高度?

news2024/11/9 2:10:14

提到 MySQL,想必大多后端同学都不会陌生,提到 B + 树,想必还是有很大部分都知道 InnoDB 引擎的索引实现,利用了 B + 树的数据结构。

那 InnoDB 的一棵 B + 树可以存放多少行数据?它又有多高呢?

到底是哪些因素会对此造成影响呢,今天我们就来展开聊一下。

  1  InnoDB 引擎数据存储

在计算机中,磁盘存储数据最小单元是扇区,一个扇区的大小是 512 字节,而文件系统(例如 XFS/EXT4)的最小单元是块,一个块的大小是 4k,在 InnoDB 存储引擎中,也有页(Page)的概念,默认每个页的大小为 16K,也就是每次读取数据时都是读取 4*4k 的大小!

 

在 MySQL 中,InnoDB 页的大小默认是 16k,当然也可以通过参数设置:

 

  2  InnoDB 引擎数据操作

接下来,为了让大家能更好地理解数据存储逻辑,我们来进行一个数据操作实例进行讲解。

假设我们现在有一个用户表,我们往里面写入数据。

 

这里需要注意的一点是,在某个页内插入新数据行时,为了减少数据的移动,通常是插入到当前行的后面或者是已删除行留下来的空间,所以在某一个页内的数据并不是完全有序的。但是为了为了数据访问顺序性,在每个记录中都有一个指向下一条记录的指针,因此构成了一条单向有序链表。

当数据还比较少时,一个页就能容下,所以只有一个根结点,主键和数据也都是保存在根结点(左边的数字代表主键,右边姓名、性别代表具体的记录数据)。

假设我们写入 10 条数据之后,Page1 满了,再写入新的数据会怎么存放呢?

 

有个叫 “无名氏” 的朋友来了,但是 Page1 已经放不下数据了,这时候就需要进行页分裂,产生一个新的 Page 页。

在 InnoDB 中的页分裂流程是怎么样的呢?

1、产生新的 Page2,然后将 Page1 的内容复制到 Page2。

2、产生新的 Page3,“无名氏” 的数据放入 Page3。

3、原来的 Page1 依然作为根结点,但是变成了一个不存放数据只存放索引的页,并且有两个子结点 Page2、Page3。

看到这里,大家可能会有两个问题:

Q1:为什么要复制 Page1 为 Page2 呢?直接创建一个新的页作为根结点,这样不就少了一次复制的开销么?

A:如果是新创建根结点,那根结点存储的物理地址可能经常会变,不利于查找。并且在 InnoDB 中根结点是会预读到内存中的,所以结点的物理地址固定会比较好。

Q2:原来 Page1 有 10 条数据,在插入第 11 条数据的时候进行页裂变,根据对 B-Tree、B+Tree 特性的了解,那这至少是一颗 11 阶的树,裂变之后每个结点的元素至少为 11/2=5 个,那是不是应该页裂变之后主键 1-5 的数据还是在原来的页,主键 6-11 的数据会放到新的页,根结点存放主键 6 呢?

A:如果是这样的话,新的页空间利用率只有 50%,并且会导致更为频繁的页分裂。所以 InnoDB 对这一点做了优化,新的数据放入新创建的页,不移动原有页面的任何记录。

随着数据的不断写入,这棵树也逐渐枝繁叶茂,如下图:

 

  每次新增数据,都是将一个页写满,然后新创建一个页继续写,这里其实是有个隐含条件的,那就是主键自增!主键自增写入时新插入的数据不会影响到原有页,插入效率高!且页的利用率高!但是如果主键是无序的或者随机的,那每次的插入可能会导致原有页频繁的分裂,影响插入效率!降低页的利用率!这也是为什么在 InnoDB 中建议设置主键自增的原因!

  这棵树的非叶子结点上存的都是主键,那如果一个表没有主键会怎么样?在 InnoDB 中,如果一个表没有主键,那默认会找建了唯一索引的列,如果也没有,则会生成一个隐形的字段作为主键!

  有数据插入那就有删除,如果这个用户表频繁的插入和删除,那会导致数据页产生碎片,页的空间利用率低,还会导致树变的 “虚高”,降低查询效率!这可以通过索引重建来消除碎片提高查询效率!

  3  InnoDB 引擎索引高度

回到开篇的问题:InnoDB 的一棵 B + 树可以存放多少行数据?它又有多高呢?

这个需要区分叶子节点和非叶子节点:

  • 非叶子节点

InnoDB 存储引擎默认一个数据页大小为 16kb,非叶子节点存放(key,pointer),假设主键 ID 为 bigint 类型,长度为 8 字节,而指针大小在 InnoDB 源码中设置为 6 字节,这样一共 14 字节,即非叶子节点能存放 16kb/14 左右的 key,pointer。

  • 叶子节点

单个叶子节点(页)中的记录数 = 16K/1K = 16。

这里我们假设一行记录的数据大小为 1k 左右

总结一下:

如果 B + 树高度为 2 的话,那么这棵 B + 树的存放总记录数为:根节点指针数 * 单个叶子节点记录行数 = 16kb/14 * 16 大约 1.8w+ 数据。

如果 B + 树高度为 3 的话,那么这棵 B + 树的存放总记录数为:根节点指针数 * 单个叶子节点记录行数 = 16kb/14 * 16kb/14 * 16 大约 2kw + 数据。

因此常见 InnoDB 存储引擎 B + 树的高度基本为 2-3


希望今天的讲解对大家有所帮助,谢谢!

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

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

相关文章

WebRTC → 信令服务器

相关简介 信令:驱动系统运转。控制各个模块的前后调用关系;业务不同,逻辑不同,信令也会千差万别 要实现一对一通信,驱动系统的核心就是信令。信令控制着系统各个模块之间的前后调用关系,比如当收到用户成功加入房间后…

3D模型在线查看利器【多种格式】

BimAnt 3DViewer网站可以 打开多种 3D 文件格式并在你的浏览器中可视化展示3D模型,支持 obj、3ds、stl、ply、gltf、glb、off、 3dm、fbx 等等。 1、支持的3D模型格式 BimAnt 3DViewer网站支持多种文件格式的导入和导出。 如果文件格式有文本和二进制版本&#x…

Minecraft 1.19.2 Fabric模组开发 09.Mixin

我们今天用mixin在1.19.2 fabric中实现一个望远镜 1.由于fabric已经自动配置好了mixin,所以我们无需配置mixin,先在ItemInit中新建一个我们的望远镜物品: ItemInit.java public static final Item BIRDWATCHER registerItem("birdwat…

Smart-doc的脚本生成在线文档(精简官方文档描述)

Smart-doc优点: 无侵入的接口文档、在线文档生成器。三种生成文档方式。对于程序代码开发中只需要加注释(符合一定的语法,五分钟可掌握)就能生成在线文档。可以支持c、java、php、node等等常见的主流语言。 如何使用: …

47.Isaac教程--ORB

ORB ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录ORBGem 提供的类型关键点描述符如何使用 Gem(界面)构建包Isaac Codelets示例应用程序主机设备嵌入式 Jetson 设备这个 gem 提供了一个特征检测器和描述符提取器…

2011年专业408算法题

文章目录0 结果1 题目2 思路2.1 思路1(暴力解:排序)2.2 思路2(较优解:归并合并数组)2.3 思路3(较优解:数组指针后移)2.4 思路4(最优解:两个数组的…

webpack是如何进行依赖图谱收集的?

我自己学习webpack已有很长时间了,但是经常会遇到这样的问题: 可以熟练配置webpack的一些常用配置,但是对一些不常见的api或者概念总是云里雾里。因此,对着网上资料手写了一个简易版的webpack,现在对其中的依赖图谱收集部分进行梳…

Numpy(7)—字节交换、NumPy 副本和视图、深浅拷贝、矩阵库、NumPy 线性代数、NumPy IO(读写)、NumPy Matplotlib

1.字节交换 import numpy as npA np.array([1, 256, 8755], dtypenp.int16) print(A) print(list(map(hex, A))) print(A.byteswap(inplaceTrue)) print(list(map(hex, A)))2.NumPy 副本和视图 副本是一个数据的完整的拷贝,如果我们对副本进行修改,它不…

【MyBatis 持久层框架】Mapper代理开发详细解读

文章目录1. 前言2. Mapper 代理开发3. 过程剖析4. 总结1. 前言 前面在 MyBatis 快速入门篇中,我们使用了 MyBatis 原生的开发方式操作数据库,解决了 JDBC 操作数据库时的硬编码和操作繁琐的问题。实际上,在 Java 项目中,我们更常…

python3——函数

目录 一、函数定义 二、函数调用 1.打印Hello World 2.判断最大值 3.计算矩形面积 4.help说明文档 三、参数传递 (一)位置参数 (二)关键字参数 (三)默认参数(缺省参数) (四)可变参数(收集参数) 1.位置可变参数(接收所有的位置参数,返回一个元组) 2.关键…

高通开发系列 - MSM8909 lk aboot阶段点灯操作

By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 目录 第一种LK提供的接口实现第二种直接操作寄存器这篇文章之前请参考下:高通开发系列 - MSM8909指示灯操作 在LK中点灯有两种方式,一种…

JAVA-定位排查bug

在开发过程中难免会遇到bug,理解bug的含义,定位bug的位置,对于解决bug至关重要!掌握高效的排错技巧,对于程序员来说必不可少。 目录 一、错误异常的分类 二、常见报错信息及原因(持续更新中)…

域内权限维持:AdminSDHolder

01、简介 AdminSDHolder是一个特殊的AD容器,通常作为某些特权组成员的对象的安全模板。Active Directory将采用AdminSDHolder对象的ACL并定期将其应用于所有受保护的AD账户和组,以防止意外和无意的修改并确保对这些对象的访问是安全的。如果攻击者能完全…

Flex布局和主要属性用法详解

目录 前言 一个小例子 基本概念: 设置在主轴上的排列方式 设置在侧轴上的排列方式 更换主轴和侧轴方向 换行 align-content属性 元素(子容器)的相关属性 flex-basis flex-grow flex-shrink属性 flex属性 前言 flex布局是继标准…

JDBC-Statement

1.Statement执行静态sql语句(“字符串”) 返回结果 2.!实际工作一般用PreparedStatement来进行sql语句的执行,因为sql注入的风险 3and4.SQl注入就是Statement没有检查我们输入sql语句,一些别有用心的可能写一些危害数据…

智能手表主控芯片盘点,智能手表GUI,智能手表市场

聚焦:无线连接芯片,市场,技术 祝大家新年快乐,开工大吉!趁寒假简单梳理了下智能手表应用,做个分享,不对的地方欢迎交流指正; 01 市场容量,分类及拓扑 2个数据供参考 一个…

C++ dll、lib 的定义以及引用,

最近在研究socket,发现socket程序要依赖ws2_32.dll,涉及到动态链接库,有点懵,上网恶补了一下链接库的知识,最后总结出这么一篇文章 链接库分为两种:动态链接库(dll) 和静态链接库(lib) 动态链接库 : 动态链…

【C++】C++11语法解析

🌈欢迎来到C专栏~~C11 (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort目前状态:大三非科班啃C中🌍博客主页:张小姐的猫~江湖背景快上车🚘,握好方向盘跟我有一起打天下嘞!送给自己的一句鸡汤&#x1f…

大数据分析案例-基于多元线性回归算法构建用户信用评分模型

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

ue4c++日记9(指定区域生成角色)

目录 创建C类 头文件 代码文件 结果 创建C类 头文件 // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "ASPawnVolum.generated…