一、序言
今天和大家讨论一下 MySQL 单表数据量多大合适。
二、B+ 树
B+ 树是一种数据结构,由分支节点和叶子节点组成。叶子节点存储数据,而分支节点仅用于索引和导航。B+ 树的叶子节点形成一个有序链表,可以通过叶子节点进行范围查询和顺序遍历。此处只对 B+ 树的概念做个引入,有关 B+ 树更详细的内容请大家借助搜索引擎哦 ^_^。
三、InnoDB 存储引擎
在 MySQL 中,默认的存储引擎是 InnoDB 存储引擎,InnoDB 存储引擎底层默认采用的是 B+ 树的数据结构。稍微不同的是:InnoDB 存储引擎的 B+ 树叶子节点采用的是双向链表而不是单向链表。
在 InnoDB 引擎中,我们的行数据是放在页中的。页(Page)是 InnoDB 存储引擎磁盘管理的最小单元,每个页的大小默认为 16 KB
。
四、MySQL 单表数据量分析
现在,我们知道 MySQL 默认采用的是 InnoDB 存储引擎来存储数据,而 InnoDB 存储引擎底层是使用的 B+ 树数据结构。为了性能,一般我们需要保证 B+ 树的高度不要超过 3。我们以最大 B+ 树高度(高度为 3)来分析,看看能存储多大的数据量。
场景假设:
- B+ 树高度为 3
- 一行数据的大小为 1KB
- 存储引擎使用 InnoDB
在 InnoDB 中,最小的存储单元是页(16 KB),那么可计算出一页可存储:16 / 1 = 16
(行)数据。
在 B+ 树中,我们知道数据存储在叶子节点,分支节点只存储索引(即 ID)和指向下一节点的指针。即:
- 分支节点存储的是行数据的 ID 和指向下一节点的指针
- 叶子节点存储的是真正的数据
InnoDB 中一个指针占用 6 个字节
,假设我们的主键使用的是 bigint(占用 8 个字节
)。那么一页可以存储多少个索引,多少个指针呢?
设:可存储索引个数为 n,则:
n ∗ 8 + ( n + 1 ) ∗ 6 = 16 ∗ 1024 n * 8 + (n + 1) * 6 = 16 * 1024 n∗8+(n+1)∗6=16∗1024
可解出 n ≈ 1170
那么,可以知道一页可存储约 1170 个索引,1170 + 1 = 1171
个指针。
我们知道 B+ 树的高度是 3,那么前两层都是索引,最后的叶子节点放的是数据,可计算出:
1171 ∗ 1171 ∗ 16 = 21939856 1171 * 1171 * 16 = 21939856 1171∗1171∗16=21939856(行)
即,树的高度为 3 时大约可以存储 2200w 行数据。
综上,我们计算出了 2200w 行是在行数据大小为 1KB(实际可能比这大),索引层数达到 3 层时的极限值,所以通常情况下我们以 2000w 为一个分界点来表述单表容量的上限。但是这只是一个参考值,因为这 2000w 的计算参数可能与我们在生产实践中的参数出入很大。