暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

为什么大家说mysql数据库单表最大两千万

原创 soul0202 2023-06-24
474

假如有一张a表,其中id是唯一主键这看起来的一行行数据,为了方便,我们后面就叫它们record吧。这张表看起来就跟个excel表格一样。excel的数据在硬盘上是一个xx.excel的文件。而a表数据,在硬盘上其实也是类似,放在了a.ibd文件下。含义是a表的innodb data文件,专业点,又叫表空间虽然在数据表里,它们看起来是挨在一起的。但实际上在a.ibd里他们被分成很多小份的数据页,每份大小16k。ibd文件内部有大量的页,类似于下面这样:


把视角聚焦一下,放到页上面:

整个页,不大,但record这么多,一页肯定放不下,所以会分开放到很多页里。并且这16k,也不可能全用来放record对吧。因为record们被分成好多份,放到好多页里了,为了唯一标识具体是哪一页,那就需要引入页号(其实是一个表空间的地址偏移量)。同时为了把这些数据页给关联起来,于是引入了前后指针,用于指向前后的页。这些都被加到了页头里。页是需要读写的,16k说小也不小,写一半电源线被拔了也是有可能发生的,所以为了保证数据页的正确性,还引入了校验码。这个被加到了页尾那剩下的空间,才是用来放我们的record的。而record如果行数特别多的话,进入到页内时挨个遍历,效率也不太行,所以为这些数据生成了一个页目录,具体实现细节不重要。只需要知道,它可以通过二分查找的方式将查找效率从O(n) 变成O(lgn)


页结构:

从页到索引,如果想查一条record,我们可以把表空间里每一页都捞出来,再把里面的record捞出来挨个判断是不是我们要找的。行数量小的时候,这么操作也没啥问题。行数量大了,性能就慢了,于是为了加速搜索,我们可以在每个数据页里选出主键id最小的record,而且只需要它们的主键id和所在页的页号。组成新的record,放入到一个新生成的一个数据页中,这个新数据页跟之前的页结构没啥区别,而且大小还是16k。但为了跟之前的数据页进行区分。数据页里加入了页层级(page level)的信息,从0开始往上算。于是页与页之间就有了上下层级的概念,就像下面这样:


两层B+树结构,突然页跟页之间看起来就像是一棵倒过来的树了。也就是我们常说的B+树索引。最下面那一层,page level 为0,也就是所谓的叶子结点,其余都叫非叶子结点上面展示的是两层的树,如果数据变多了,我们还可以再通过类似的方法,再往上构建一层。就成了三层的树。


三层B+树结构:

那现在我们就可以通过这样一棵B+树加速查询。举个例子。比方说我们想要查找行数据5。会先从顶层页的record们入手。record里包含了主键id和页号(页地址)。看下图黄色的箭头,向左最小id是1,向右最小id是7。那id=5的数据如果存在,那必定在左边箭头。于是顺着的record的页地址就到了数据页里,再判断id=5>4,所以肯定在右边的数据页里,于是加载数据页。在数据页里找到id=5的数据行,完成查询。


B+树查询过程:

另外需要注意的是,上面的页的页号并不是连续的,它们在磁盘里也不一定是挨在一起的。这个过程中查询了三个页,如果这三个页都在磁盘中(没有被提前加载到内存中),那么最多需要经历三次磁盘IO查询,它们才能被加载到内存中。B+树承载的记录数量,从上面的结构里可以看出B+树的最末级叶子结点里放了record数据。而非叶子结点里则放了用来加速查询的索引数据。也就是说,同样一个16k的页,非叶子节点里每一条数据都指向一个新的页,而新的页有两种可能。

如果是末级叶子节点的话,那么里面放的就是一行行record数据。如果是非叶子节点,那么就会循环继续指向新的数据页。假设非叶子结点内指向其他内存页的指针数量为叶子节点内能容纳的record数量为B+树的层数为


总行数的计算方法,那这棵B+树放的行数据总量


非叶子节点里主要放索引查询相关的数据,放的是主键和指向页号。主键假设是bigint 8byte,而页号在源码里叫fil_page_offset 大小是4byte,那么非叶子节点里的一条数据是12字节左右。整个数据页, 页头页尾那部分数据全加起来大概,加上页目录毛估占吧。那剩下的15k除以12byte,也就是可以指向x=1280页叶子节点放的真正的行数据,假设有一条数据大小为1k,则y=15。假设b+树三层,则根据公式活得2.5kw数据行。

上面假设单行数据用了1kb,所以一个数据页能放个15行数据。如果我单行数据用不了这么多,比如只用了250byte。那么单个数据页能放60行数据。那同样是三层B+树,单表支持的行数就是60行。由公式得出一个亿的数据,其实也就三层B+树,在这个B+树里要查到某行数据,最多也是三次磁盘IO。所以并不慢。



「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论