面试官:单表能存多少数据?

2024-07-26 19:10:31 浏览数 (2)

面试中难免会被问到单表能存多少数据?

可能很多人都看过网上的一些文章说最多只能存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万行后,只是个建议,毕竟实际场景中有的表上亿了也能正常使用。

你见过一张表最多存多少数据?欢迎打在评论区里。

0 人点赞