面试中难免会被问到单表能存多少数据?
可能很多人都看过网上的一些文章说最多只能存2000万。你觉得呢?
还有,在阿里开发规范中有这么一条:
这里人家说推荐进行分库分表,不是强制进行分库分表。
然后,我记得2017年,我面试过一家小企业,面试中就被问到一个表数据达到多少时需要做分库分表。
我当时回答是:这个没有具体的值,要看你的表结构设计,以及当前硬件配置,不是看到有多少数据了就开始搞分库分表,因为分库分表不是闹着玩的,从系统架构的复杂度和工期来说都会相应增加。
那个面试官反问我:你没有看过阿里的开发规范吗?人家都是说500万行了就得进行分库分表,这个面试官忘了后面还有容量的条件,我当时真的想笑,也像吐血了,怎么会有这样的面试官。
今天,我们聊聊到底一张表可以存多少数据。
我们先来看一个三层的B 树到底能存多少数据。
我们都知道一颗B 树是由一个一个磁盘页组成的,其中,每一页的大小我们可以通过命令:
代码语言:javascript复制show global status like 'innodb_page_size'
一页的大小是16384个字节,也就是16KB。
每一页它的结构是这样的:
名称 | 中文名称 | 占用空间大小 | 简单描述 |
---|---|---|---|
File Header | 文件头部 | 38字节 | 页的一些通用信息 |
Page Header | 页面头部 | 56字节 | 数据页专有的一些信息 |
Infimum Supremum | 最小记录和最大记录 | 26字节 | 两个虚拟的行记录 |
User Records | 用户记录 | 不确定 | 实际存储的行记录内容 |
Free Space | 空闲空间 | 不确定 | 页中尚未使用的空间 |
Page Directory | 页面目录 | 不确定 | 页中的某些记录的相对位置 |
File Trailer | 文件尾部 | 8字节 | 校验页的完整 |
每个也为16KB,减去页头和页尾的总开销(差不多200字节),用于存储实际数据的有效空间就差不多是16384-200=16184.
这里我们知道了一页能存多少字节了,那我们就只需要知道表里的一行数据他有多少个字节。
16184除以一行数据的字节数,就差不多能算出一页能存多少行数据了。
假设现在有一张表:
代码语言:javascript复制CREATE TABLE t1(
a int(11) PRIMARY KEY,
b int(11),
c int(11),
d int(11),
e varchar(20) CHARACTER SET utf8mb4
)ENGIN=InnoDB
a列占用4字节,b、c、d都是4字节。
e列需要安装编码格式来,就是:4n 2
所以,总的计算是4 4 4 4 (20*4) 2=98字节,为了好计算我们就假设是100字节。
上面我们已经知道一页是16184字节,16184除以100=161,就是最多能存161行数据。
那我们再来看一下一个三层的B 树能存放多少行,为什么以三层B 树来聊,是因为三层是一个相对比较理想的范围,只需要三次的磁盘IO就能定位到数据。
三层B 树的层次指的是根节点、内部节点和叶子节点,总共包含三层。根节点是第一层,内部节点是第二层,叶子节点是第三层。
每个节点(无论是内部节点还是叶子节点)可以存储多个指针和键值对,具体取决于页的大小(通常为16KB)和每个记录的大小,这个前面已经算出来是161。
我们都知道非叶子节点不会存数据,只会存索引以及指针,指针占用6个字节,每个索引int占用4个字节,所以加起来就是10个字节,那么一页16184除以10字节=1618(索引 指针)。
由于是三层,那么第三层的叶子节点就是1618乘以1618,大概是2617924个节点。
再就是每个叶子节点能存161行记录,那整个三层B 树就是2617924乘以161,大概4.2亿。
回到上面的问题中你还会觉得一张表的最多能存2000万是正确的吗?
其实,抛开容量来聊一张表能存多少数据是不对的。
上面的案例中,一行记录是100字节,假设我们一行记录是1KB,那也就意味着差不多能存4000万行,也比2000万貌似还多。
阿里开发规范可能是考虑到了资源性能,毕竟以前的硬盘都是机械硬盘,现在基本上都是固态硬盘,所以这个数据也是可以适当往上再调整调整。另外也可能是考虑到数据的备份和恢复的风险系数会增加,所以,个人认为一张表的数据如果达到1000万行后,只是个建议,毕竟实际场景中有的表上亿了也能正常使用。
你见过一张表最多存多少数据?欢迎打在评论区里。