当前位置: 首页 > 科技观察

心态崩了,我怎么知道实际生产环境中的B+树索引有多少层呢?

时间:2023-03-20 18:42:51 科技观察

Q:在实际生产环境中,InnoDB中的B+树索引一般有多少层?它可以存储多少行数据?关于这个问题,最近好像经常在牛客上看到。重要的是对B+指数的理解。先回答:A:一般有2到3层,可以存储2000万行左右的数据。如前所述,页面是InnoDB磁盘管理的最小单位。在InnoDB存储引擎中,每页的默认大小为16KB。而页面中存放的东西,都是一行一行的记录。假设一行数据的大小为1k,那么一页可以存储16行这样的数据。众所周知,B+树的叶子节点存放的是真实的记录,非叶子节点的存在是为了更快的找到相应记录所在的叶子节点,所以可以简单理解为非叶子节点存放的是键值+指针。这里用指针来描述描述不是很准确。准确的说是页的偏移量,不过指针更好理解~通过索引组织表,将数据行存储在不同的页中。如下图所示:假设我们要从上图中的B+树中找出主键为20的那一行数据。Select*fromtablewhereid=20;首先找到B+树的根节点,即存储的非叶子节点的page_number=10,在这个page上,通过二分查找的方式和指针定位到id=20的那一行数据,存在于page_number=12,然后在这个页面使用二分查找快速定位到id=20的行。说到这些和文章标题关系不大的话题,只想让大家知道:作为InnoDB的最小单位磁盘管理,一个页不仅可以存放具体的行数据,还可以存放键值和指针。回到问题,我们先从一个简单的开始,假设B+树只有两层,即一个根节点和几个叶子节点,如下图所示:那么可以存储多少行数据在这棵B+树中,问题其实就是这棵树B+树的非叶子节点存储的数据量,可以通过下面简单的公式计算:根节点指针数*每个叶子节点存储的行记录数每个叶子节点存储的行记录数就是每页存储的行数记录数,由于每个数据表的字段数不同,这里我们先不深究叶子节点的存储结构,简单的按照一行记录的数据大小为1k计算(其实很多互联网业务数据记录的大小通常在1K左右),一个页面或者一个叶子节点可以存储16行这样的数据。那么B+号的根节点(非叶子节点)到底能存储多少数据呢?非叶子节点存放的是主键值+指针。我们假设主键的类型是BigInt,长度是8个字节,指针大小在InnoDB中设置为6个字节,所以一共是14个字节。为了书写方便,这里我们称一个主键值+一个指针为一个单元,这样一个页或者一个非叶子节点可以存储16384/14=1170个这样的单元。也就是说一个非叶子节点可以存放1170个指针,对应1170个叶子节点,所以对于这样一棵高度为2的B+树,它可以存放1170个(非叶子节点的指针个数)*16(叶子节点的行数)=18720行数据。当然,这种分析其实不是很严谨。根据《MySQL 技术内幕:InnoDB 存储引擎》中的定义,InnoDB的数据页结构包括以下几个部分:想深入研究的可以看书中的4.4章,这里不再分析。OK,分析完高度为2的B+树,同理我们再看高度为3的:根页(page10)可以存放1170个指针,第二层的每一页(page:11,12,13)也可以分别存储1170个指针。这样一共可以存储1170*1170个指针,即对应有1170*1170个非叶子节点,所以一共可以存储1170*1170*16=21902400行记录。