当前位置: 首页 > news >正文

【MySql】InnoDB一棵B+树可以存放多少行数据?

文章目录

  • 背景
  • 一、怎么得到InnoDB主键索引B+树的高度?
  • 二、小结
  • 三、最后回顾一道面试题
  • 总结
  • 参考资料

背景

InnoDB一棵B+树可以存放多少行数据?这个问题的简单回答是:约2千万。为什么是这么多呢?因为这是可以算出来的,要搞清楚这个问题,我们先从InnoDB索引数据结构、数据组织方式说起。

我们都知道计算机在存储数据的时候,有最小存储单元,这就好比我们今天进行现金的流通最小单位是一毛。在计算机中磁盘存储数据最小单元是扇区,一个扇区的大小是512字节,而文件系统(例如XFS/EXT4)他的最小单元是块,一个块的大小是4k,而对于我们的InnoDB存储引擎也有自己的最小储存单元——页(Page),一个页的大小是16K。

下面几张图可以帮你理解最小存储单元:

文件系统中一个文件大小只有1个字节,但不得不占磁盘上4KB的空间。

在这里插入图片描述

innodb的所有数据文件(后缀为ibd的文件),他的大小始终都是16384(16k)的整数倍。
在这里插入图片描述

磁盘扇区、文件系统、InnoDB存储引擎都有各自的最小存储单元。

在这里插入图片描述

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

mysql> show variables like 'innodb_page_size';+------------------+-------+| Variable_name    | Value |+------------------+-------+| innodb_page_size | 16384 |+------------------+-------+1 row in set (0.00 sec)

数据表中的数据都是存储在页中的,所以一个页中能存储多少行数据呢?假设一行数据的大小是1k,那么一个页可以存放16行这样的数据。

如果数据库只按这样的方式存储,那么如何查找数据就成为一个问题,因为我们不知道要查找的数据存在哪个页中,也不可能把所有的页遍历一遍,那样太慢了。所以人们想了一个办法,用B+树的方式组织这些数据。如图所示:

在这里插入图片描述

我们先将数据记录按主键进行排序,分别存放在不同的页中(为了便于理解我们这里一个页中只存放3条记录,实际情况可以存放很多),除了存放数据的页以外,还有存放键值+指针的页,如图中page number=3的页,该页存放键值和指向数据页的指针,这样的页由N个键值+指针组成。当然它也是排好序的。这样的数据组织形式,我们称为索引组织表。现在来看下,要查找一条数据,怎么查?

select * from user where id=5;

这里id是主键,我们通过这棵B+树来查找,首先找到根页,你怎么知道user表的根页在哪呢?其实每张表的根页位置在表空间文件中是固定的,即page number=3的页(这点我们下文还会进一步证明),找到根页后通过二分查找法,定位到id=5的数据应该在指针P5指向的页中,那么进一步去page number=5的页中查找,同样通过二分查询法即可找到id=5的记录:

5zhao227

现在我们清楚了InnoDB中主键索引B+树是如何组织数据、查询数据的,我们总结一下:

  1. InnoDB存储引擎的最小存储单元是页,页可以用于存放数据也可以用于存放键值+指针,在B+树中叶子节点存放数据,非叶子节点存放键值+指针。

  2. 索引组织表通过非叶子节点的二分查找法以及指针确定数据在哪个页中,进而在去数据页中查找到需要的数据;

那么回到我们开始的问题,通常一棵B+树可以存放多少行数据?

这里我们先假设B+树高为2,即存在一个根节点和若干个叶子节点,那么这棵B+树的存放总记录数为:根节点指针数*单个叶子节点记录行数。

上文我们已经说明单个叶子节点(页)中的记录数=16K/1K=16。(这里假设一行记录的数据大小为1k,实际上现在很多互联网业务数据记录大小通常就是1K左右)。

那么现在我们需要计算出非叶子节点能存放多少指针,其实这也很好算,我们假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,这样一共14字节,我们一个页中能存放多少这样的单元,其实就代表有多少指针,即16384/14=1170。那么可以算出一棵高度为2的B+树,能存放1170*16=18720条这样的数据记录。

根据同样的原理我们可以算出一个高度为3的B+树可以存放:1170117016=21902400条这样的记录。所以在InnoDB中B+树高度一般为1-3层,它就能满足千万级的数据存储。在查找数据时一次页的查找代表一次IO,所以通过主键索引查询通常只需要1-3次IO操作即可查找到数据。

一、怎么得到InnoDB主键索引B+树的高度?

上面我们通过推断得出B+树的高度通常是1-3,下面我们从另外一个侧面证明这个结论。在InnoDB的表空间文件中,约定page number为3的代表主键索引的根页,而在根页偏移量为64的地方存放了该B+树的page level。如果page level为1,树高为2,page level为2,则树高为3。即B+树的高度=page level+1;下面我们将从实际环境中尝试找到这个page level。

在实际操作之前,你可以通过InnoDB元数据表确认主键索引根页的page number为3,你也可以从《InnoDB存储引擎》这本书中得到确认。

SELECT
b.name, a.name, index_id, type, a.space, a.PAGE_NO
FROM
information_schema.INNODB_SYS_INDEXES a,
information_schema.INNODB_SYS_TABLES b
WHERE
a.table_id = b.table_id AND a.space <> 0;

执行结果:
在这里插入图片描述

可以看出数据库dbt3下的customer表、lineitem表主键索引根页的page number均为3,而其他的二级索引page number为4。关于二级索引与主键索引的区别请参考MySQL相关书籍,本文不在此介绍。

下面我们对数据库表空间文件做想相关的解析:

在这里插入图片描述

因为主键索引B+树的根页在整个表空间文件中的第3个页开始,所以可以算出它在文件中的偏移量:16384*3=49152(16384为页大小)。

另外根据《InnoDB存储引擎》中描述在根页的64偏移量位置前2个字节,保存了page level的值,因此我们想要的page level的值在整个文件中的偏移量为:16384*3+64=49152+64=49216,前2个字节中。

接下来我们用hexdump工具,查看表空间文件指定偏移量上的数据:

在这里插入图片描述

linetem表的page level为2,B+树高度为page level+1=3;

region表的page level为0,B+树高度为page level+1=1;

customer表的page level为2,B+树高度为page level+1=3;

这三张表的数据量如下:

在这里插入图片描述

二、小结

lineitem表的数据行数为600多万,B+树高度为3,customer表数据行数只有15万,B+树高度也为3。可以看出尽管数据量差异较大,这两个表树的高度都是3,换句话说这两个表通过索引查询效率并没有太大差异,因为都只需要做3次IO。那么如果有一张表行数是一千万,那么他的B+树高度依旧是3,查询效率仍然不会相差太大。

region表只有5行数据,当然他的B+树高度为1。

三、最后回顾一道面试题

有一道MySQL的面试题,为什么MySQL的索引要使用B+树而不是其它树形结构?比如B树?

现在这个问题的复杂版本可以参考本文;

他的简单版本回答是:

因为B树不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出),指针少的情况下要保存大量数据,只能增加树的高度,导致IO操作变多,查询性能变低;

总结

本文从一个问题出发,逐步介绍了InnoDB索引组织表的原理、查询方式,并结合已有知识,回答该问题,结合实践来证明。当然为了表述简单易懂,文中忽略了一些细枝末节,比如一个页中不可能所有空间都用于存放数据,它还会存放一些少量的其他字段比如page level,index number等等,另外还有页的填充因子也导致一个页不可能全部用于保存数据。关于二级索引数据存取方式可以参考MySQL相关书籍,他的要点是结合主键索引进行回表查询。

参考资料

姜承尧 《MySQL技术内幕:InnoDB存储引擎》

姜承尧 http://www.innomysql.com/查看-innodb表中每个的索引高度/

相关文章:

【MySql】InnoDB一棵B+树可以存放多少行数据?

文章目录 背景一、怎么得到InnoDB主键索引B树的高度&#xff1f;二、小结三、最后回顾一道面试题总结参考资料 背景 InnoDB一棵B树可以存放多少行数据&#xff1f;这个问题的简单回答是&#xff1a;约2千万。为什么是这么多呢&#xff1f;因为这是可以算出来的&#xff0c;要搞…...

【综述】视频无监督域自适应(VUDA)的小综述

【综述】视频无监督域自适应&#xff08;VUDA&#xff09;的小综述 一篇小综述&#xff0c;大家看个乐子就好&#xff0c;参考文献来自于一篇综述性论文 完整PPT已经上传资源&#xff1a;https://download.csdn.net/download/weixin_46570668/87848901?spm1001.2014.3001.550…...

《深入理解计算机系统(CSAPP)》第9章虚拟内存 - 学习笔记

写在前面的话&#xff1a;此系列文章为笔者学习CSAPP时的个人笔记&#xff0c;分享出来与大家学习交流&#xff0c;目录大体与《深入理解计算机系统》书本一致。因是初次预习时写的笔记&#xff0c;在复习回看时发现部分内容存在一些小问题&#xff0c;因时间紧张来不及再次整理…...

信息论与编码 SCUEC DDDD 期末复习

1.证明熵的可加性 2.假设一帧视频图像可以认为是由3*10的五次方个像素组成&#xff08;每像素均独立变化&#xff09;&#xff0c;如果每个像素可取128个不同的等概率亮度表示。请计算出每帧图像含多少信息量&#xff1f;若有一口述者在约12000个汉字的字汇中选400个字来口述此…...

windows安装python开发环境

最近因工作需要&#xff0c;要学习一下python&#xff0c;所以先安装一下python的开发环境&#xff0c;比较简单 下载和安装Python 首先&#xff0c;在浏览器中打开Python的官方网站&#xff08;https://www.python.org/downloads/) 然后&#xff0c;从该网站下载与你的操…...

java idea常用的快捷方式

文章目录 java idea常用的快捷方式快速复制选多行改变代码格式化 快速代码编辑psvmsout5.forarr.for快速死循环快速补全代码当方法还没创建的时候抽取具有一定功能的代码变成方法 java idea常用的快捷方式 快速复制 c t r l d \color{red}{ctrld} ctrld 选多行改变 A l t 鼠…...

lwIP 开发指南

目录 lwIP 初探TCP/IP 协议栈是什么TCP/IP 协议栈架构TCP/IP 协议栈的封包和拆包 lwIP 简介lwIP 源码下载lwIP 文件说明 MAC 内核简介PHY 芯片介绍YT8512C 简介LAN8720A 简介 以太网接入MCU 方案软件TCP/IP 协议栈以太网接入方案硬件TCP/IP 协议栈以太网接入方案 lwIP 无操作系…...

RabbitMQ消息属性详解

content-type属性 如同各种标准化的HTTP规范&#xff0c;content-type传输消息体的MIME类型。例如&#xff0c;如果你的应用程序正在发送JSON序列化的数据值&#xff0c;那么将content-type属性设置为application/json将允许尚待开发的消费者应用程序在收到消息时检查消息类型…...

shader 混合模式

在所有着色器执行完毕&#xff0c;所有纹理都被应用&#xff0c;所有像素准备被呈现到屏幕之后&#xff0c;使用Blend命令来操作这些像素进行混合。 3.2 blend的语法 BlendOff:关闭blend混合&#xff08;默认值&#xff09; BlendSrcFactor DstFactor &#xff1a;配置并启动混…...

【大数据工具】Hive 安装

Hive 环境搭建与基本使用 Hive 安装包下载地址&#xff1a;https://dlcdn.apache.org/hive/ 注&#xff1a;安装 Hive 前要先安装好 MySQL 1. MySQL 安装 MySQL 安装包下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/archives/community/MySQL%20::%20Downloa…...

Android9.0 iptables用INetd实现app某个时间段禁止上网的功能实现

1.前言 在9.0的系统rom定制化开发中,在system中netd网络这块的产品需要中,会要求设置app某个时间段禁止上网的功能,liunx中iptables命令也是比较重要的,接下来就来在INetd这块实现app某个时间段禁止上网的的相关功能,就是在系统中只能允许某个app某个时间段禁止上网,就是…...

webpack.config.js基础配置(五大核心属性)

在上一节webpack零基础入门中我们在安装完webpack 和 webpack-cli依赖之后&#xff0c;直接通过npx webpack ./src/main.js --modedevelopment的方式对src下的js文件进行了打包。 其中的 ./src/main.js: 指定 Webpack 从 main.js 文件开始打包&#xff0c;不但会打包 main.js&a…...

【华为OD机试】阿里巴巴找黄金宝箱(IV)【2023 B卷|200分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 一贫如洗的樵夫阿里巴巴在去砍柴的路上,无意中发现了强盗集团的藏宝地, 藏宝地有编号从0-N的箱子,每个箱子上面有一个数字,箱子排列成一个环, 编号最大的箱子的下一个是编号为0的箱…...

Qt6 C++基础入门2 文件结构与信号和槽

目录 标准文件结构widget.hwidget.cppmain.cpppro 文件 信号与槽自定义信号connect 的两种方式 标准文件结构 widget.h widget 对象的头文件 一般会直接在头文件导入所有后续在 cpp 文件内用到的类&#xff0c;所以 include 基本都会写在这里 // 头文件标志起始 #ifndef WID…...

常用模拟低通滤波器的设计——契比雪夫II型滤波器

常用模拟低通滤波器的设计——契比雪夫II型滤波器 切比雪夫 II 型滤波器的振幅平方函数为&#xff1a; 式中&#xff0c;为有效带通截止频率&#xff0c; 是与通带波纹有关的参量&#xff0c; 大&#xff0c;波纹大&#xff0c;&#xff1b; 为 N 阶契比雪夫多项式。 在 Matl…...

SSM 如何使用 Redis 实现缓存?

SSM 如何使用 Redis 实现缓存&#xff1f; Redis 是一个高性能的非关系型数据库&#xff0c;它支持多种数据结构和多种操作&#xff0c;可以用于缓存、队列、计数器等场景。在 SSM&#xff08;Spring Spring MVC MyBatis&#xff09;开发中&#xff0c;Redis 可以用来实现数…...

uin-app如何获取微信昵称和头像的博客

在很多应用中都会使用到微信登录功能&#xff0c;这样可以方便用户快速地完成注册、登录等操作。本文将介绍如何通过uin-app获取微信用户的昵称和头像信息。 第一步&#xff1a;准备开发环境 首先&#xff0c;需要下载并安装QQ精简版开发工具&#xff08;uin-app&#xff09;…...

第六十七天学习记录:对陈正冲编著《C 语言深度解剖》中关于变量命名规则的学习

最近开始在阅读陈正冲编著的《C 语言深度解剖》&#xff0c;还没读到十分之一就感觉收获颇多。其中印象比较深刻的是其中的变量的命名规则。 里面提到的不允许使用拼音正是我有时候会犯的错。 因为在以往的工作中&#xff0c;偶尔会遇到时间紧迫的情况。 而对于新增加的变量不知…...

matlab 计算点云的线性指数

目录 一、算法原理二、代码实现三、结果展示一、算法原理 选取当前点 p i ( x , y , z ) p_{i}(x,y,z) p<...

SpringBoot集成ElasticSearch

文章目录 前言一、ElasticSearch本地环境搭建二、SpringBoot整合ElasticSearch1.pom中引入ES依赖2.application.yaml配置elasticsearch3.ElasticSearchClientConnect连接ES客户端工具类4.ElasticSearchResult封装响应结果5.Person实体类6.Person实体类7.ElasticsearchControlle…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...

Java数组Arrays操作全攻略

Arrays类的概述 Java中的Arrays类位于java.util包中&#xff0c;提供了一系列静态方法用于操作数组&#xff08;如排序、搜索、填充、比较等&#xff09;。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序&#xff08;sort&#xff09; 对数组进行升序…...

手动给中文分词和 直接用神经网络RNN做有什么区别

手动分词和基于神经网络&#xff08;如 RNN&#xff09;的自动分词在原理、实现方式和效果上有显著差异&#xff0c;以下是核心对比&#xff1a; 1. 实现原理对比 对比维度手动分词&#xff08;规则 / 词典驱动&#xff09;神经网络 RNN 分词&#xff08;数据驱动&#xff09…...

用 FFmpeg 实现 RTMP 推流直播

RTMP&#xff08;Real-Time Messaging Protocol&#xff09; 是直播行业中常用的传输协议。 一般来说&#xff0c;直播服务商会给你&#xff1a; ✅ 一个 RTMP 推流地址&#xff08;你推视频上去&#xff09; ✅ 一个 HLS 或 FLV 拉流地址&#xff08;观众观看用&#xff09;…...

循环语句之while

While语句包括一个循环条件和一段代码块&#xff0c;只要条件为真&#xff0c;就不断 循环执行代码块。 1 2 3 while (条件) { 语句 ; } var i 0; while (i < 100) {console.log(i 当前为&#xff1a; i); i i 1; } 下面的例子是一个无限循环&#xff0c;因…...

Linux【5】-----编译和烧写Linux系统镜像(RK3568)

参考&#xff1a;讯为 1、文件系统 不同的文件系统组成了&#xff1a;debian、ubuntu、buildroot、qt等系统 每个文件系统的uboot和kernel是一样的 2、源码目录介绍 目录 3、正式编译 编译脚本build.sh 帮助内容如下&#xff1a; Available options: uboot …...