Innodb的B+树索引到底能存多少数据

2023-11-20 14:30

本文主要是介绍Innodb的B+树索引到底能存多少数据,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Innodb的B+树能存多少数据

Innodb的数据组织的最小位是page,默情况下,page的大小16K

索引B+树的组织方式是:主键索引树是按照聚簇索引的方式,即叶子节点存数据,非叶子节点存线索,也就是说,一张Innodb表一定会有一棵主键索引树。并且非叶子节点的大小保持相等等于16K(为了IO方便,一次IO从磁盘读取一个page的大小,写入的时候也是一次IO写入一个page的大小)。所以有了这个,B+树上的节点的大小就是确定的,就是16K了,而B+树是一个m-n排序树,所以一个节点就是主键ID+指针(指向孩子节点的指针)构成的。

如下就是一个只有2层的B+树示意图:

  1. 非叶子节点:存的就是主键索引的线索。
  2. 叶子节点:注意并不是所有的行数据都在叶子节点上,只是父节点中线索指向的那些节点在树上,如上图,两个灰色的其实就不再树上。

所以行数据的组织方式是以page为最小单位,按照链表的方式来组织的。非叶子节点上的线索指向的叶子节点就算是在树上。而对于也字节点,一个page内是存放了多条行记录的,这多条记录是按照索引从小大大排序的,所以查询的过程首先是根据B+树索引定位到具体的page,然后page内使用二分法去找具体的行数据。

所以,叶子节点是个链表,理论上可以无限大,但是非叶子节点就是一个16k大小的page,所以对于一棵树能存多少数据,主要就看非叶节点能存下多少个[主键ID+指针]了。

ps:一个节点有多少个[主键ID+指针],其实就是m树的m是多大了。

下面以一个高度=2,且主键ID是一个bigint(8字节)来分析可以存下多少数据(这个假设是有意义的,在绝大部分主键id都是一个自增的bigint)。

Innodb中一个指针是6字节长度。所以[主键ID+指针]总共就占14字节。所以一个16K大小的节点可以存下的[主键ID+指针]个数=16K/14=16384/14=1170也就是说一个高度=2的B+树可以放下1170个叶子节点,即1170个用于存放行数据的page,即可以存放的行数据的大小=1170*16K=18720K=18M,准确的说这是树上的,还有很多不在树上的,所以实际能放下的数据不止1.8M。

ps:一个page内还有一些其他的数据,如next指针,LSN等,所以说一个page的16K不完全都拿来存行数据的。

如果下面我们分析高度=3,即有两层非叶子节点的B+树,能存放多少数据。根节点的16k的page可以存放16k/14=1170个[主键ID+指针],即第二层就可以有1170个page。所以总共树上可以放的叶子节点的个数=1170*1170=1368900,所以能放下的数据=1368900*16K=21902400K=21G。同理,因为不是所有的行数据都在树上,所以高度=3的B+树不止放下21G的数据的。

再来,看下高度=4的,那么树上可以存下的叶子节点=1170*1170*1170=1601613000个,所以能存下的数据=1601613000*16K=25.6T。同理,实际存下的数据是可以不止这个量的。

所以,在实际中,绝大部分的表的索引树的高度都不会超过4。

ps:曾经遇到一个问题,聚簇索引叶子节点存数据,非叶子节点存索引,为什么这么设计,非叶子节点也存数据可不可以

我当时的回答:没必要,如果存了,确实能满足查询这个而需求,但是没必要,而且索引会加载到内存,如果非叶子节点放数据,那么会占用大量内存。

然后我将这个问题抛给另外一个大佬:大佬大概的说法是,影响读写,因为如果将非叶子节点存数据,那么一次IO读取的数据是有限的,影响性能。

我们现在来回答这个问题:大佬的回答其实是没问题的,只是跟IO没关系。如果非叶子节点存数据,那么一个节点能存下的数据就会少很多,对于一些大表,一个page都放不下一行数据。所以这种情况,势必会增大树的高度。一个极端情况,一个page只能存下一行记录,那么B+树其实就退化成链表了,如果我们想要查的数据在最后面,想想这个效率。如果总共有n条数据,那么就需要n次IO,如果是这样,这个系统几乎是没法使用的,数据量稍微一大,就没法搞了,而且性能非常不稳定。而且,当一个page放不下一行的时候,还面临如何拆分存储的问题,复杂度也更高了。

说到这,追问问题就来了,叶子节点存行数据,如果一行特别大怎么搞?第一:首先mysql一张表支持的字段数是有限的,第二:如若是大字段,如text,blog,varchar(很大),实际存储在树上的,只是前k个字节(k的具体值忘了)。另外对于字符串类型的字段,mysql是支持前缀索引的 ,现在也大概明白为啥要这么支持了吧,我个人觉得就是mysql本身是有这个限制的(page的大小限制),那么对于这种大字段,需要让使用者合理的去使用提供的功能。

ps:任何组件,任何框架都有它适合的场景,以及最佳实践方式,我们要做的就是去发现它的限制,以最佳实践的方式去使用他,这一点很重要,没有一个框架提供一个银弹解决方案的,一定要有取舍,取其长避其短。举个例子,mysql也支持倒排索引,但是你真的要用mysql作全文搜搜,Elasticsearch不香么?对于分页from+size的方式会有身份也的问题,比如es就有默认1w的限制,但是对于一个搜索功能,如果前1w条召回的记录都不能满足你的要求,你的搜索排序得由多不准啊,而且正常人有耐心给你翻1w行,如果你要杠精的说黑客?这不正是1w条限制的原因么,这是框架的一个自我保护机制啊。如果你要继续杠,老子要数据迁移,咋整,大佬给你想到了,scroll不香么。同样的,mysql的limit分页的问题不是一样的么,如果这不好理解,分库分表的分页就很明显了

B+树的高度

上面分析一个B+树能存下多少数据的时候,其实我们都是假设了树的高度。那么问题来了,Innodb中,树的高度是怎么确定的呢?

在Innodb中,是不能直接设定树的高度,或者m树的m的大小的,但是自mysql5.7后,提供了一个设定page大小的参数innodb_page_size,默认值是16K。

我们可以通过来改变page的大小来简介改变m树的m的大小。而page的大小也会间接影响到树的高度,比如我们现在要存20G大小的数据,那么page=16K和page=4K,树的高度是不一样的。换句话说,树的高度是根据你要存下的数据是多少来决定的。

另外这篇文章解释了一些背景以及作了一些实验:https://mp.weixin.qq.com/s/ceMTuWeL5DGQ2g-XjcEj0A

这篇关于Innodb的B+树索引到底能存多少数据的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/395281

相关文章

MySQL 删除数据详解(最新整理)

《MySQL删除数据详解(最新整理)》:本文主要介绍MySQL删除数据的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、前言二、mysql 中的三种删除方式1.DELETE语句✅ 基本语法: 示例:2.TRUNCATE语句✅ 基本语

MyBatisPlus如何优化千万级数据的CRUD

《MyBatisPlus如何优化千万级数据的CRUD》最近负责的一个项目,数据库表量级破千万,每次执行CRUD都像走钢丝,稍有不慎就引起数据库报警,本文就结合这个项目的实战经验,聊聊MyBatisPl... 目录背景一、MyBATis Plus 简介二、千万级数据的挑战三、优化 CRUD 的关键策略1. 查

python实现对数据公钥加密与私钥解密

《python实现对数据公钥加密与私钥解密》这篇文章主要为大家详细介绍了如何使用python实现对数据公钥加密与私钥解密,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录公钥私钥的生成使用公钥加密使用私钥解密公钥私钥的生成这一部分,使用python生成公钥与私钥,然后保存在两个文

MySQL之InnoDB存储引擎中的索引用法及说明

《MySQL之InnoDB存储引擎中的索引用法及说明》:本文主要介绍MySQL之InnoDB存储引擎中的索引用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1、背景2、准备3、正篇【1】存储用户记录的数据页【2】存储目录项记录的数据页【3】聚簇索引【4】二

mysql中的数据目录用法及说明

《mysql中的数据目录用法及说明》:本文主要介绍mysql中的数据目录用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、版本3、数据目录4、总结1、背景安装mysql之后,在安装目录下会有一个data目录,我们创建的数据库、创建的表、插入的

MySQL中的InnoDB单表访问过程

《MySQL中的InnoDB单表访问过程》:本文主要介绍MySQL中的InnoDB单表访问过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、访问类型【1】const【2】ref【3】ref_or_null【4】range【5】index【6】

MySQL之InnoDB存储页的独立表空间解读

《MySQL之InnoDB存储页的独立表空间解读》:本文主要介绍MySQL之InnoDB存储页的独立表空间,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、独立表空间【1】表空间大小【2】区【3】组【4】段【5】区的类型【6】XDES Entry区结构【

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

Navicat数据表的数据添加,删除及使用sql完成数据的添加过程

《Navicat数据表的数据添加,删除及使用sql完成数据的添加过程》:本文主要介绍Navicat数据表的数据添加,删除及使用sql完成数据的添加过程,具有很好的参考价值,希望对大家有所帮助,如有... 目录Navicat数据表数据添加,删除及使用sql完成数据添加选中操作的表则出现如下界面,查看左下角从左

MySQL中的索引结构和分类实战案例详解

《MySQL中的索引结构和分类实战案例详解》本文详解MySQL索引结构与分类,涵盖B树、B+树、哈希及全文索引,分析其原理与优劣势,并结合实战案例探讨创建、管理及优化技巧,助力提升查询性能,感兴趣的朋... 目录一、索引概述1.1 索引的定义与作用1.2 索引的基本原理二、索引结构详解2.1 B树索引2.2