Mysql-为什么说单张表数据超过2000w,性能就会下降

其实2000w只是一个建议值

假设有一张user表,其中id是主键

user表:
idnameage
1张三18
2李四19

存在磁盘中的文件为user.idb(innodb data)的表空间。数据再idb文件中被分成了很多小份的数据页,每份大小16k

 行数据被放在了不同的数据页中

页号:区分是那一页 

pre:指向上一页

next:指向下一页

页目录:用于快速查找(如果数据特别多的时候一行一行的查找数据太慢),可通过二分查找的方式将查询效率从O(n)变成O(lgn)

校验码:在页尾,防止数据再写入的时候发生异常(断电等)

中间部分:1、2、3、...存放真正的行数据

怎么在数据也中查找数据:

1、如果想查找一行数据,可以将表空间中的每一页都捞出来,在判断里面的行数据,是不是最终要查询的数据。

2、数据小的话没问题,但是数据大的时候这么查找会变慢。

为了加速查找,引入了B+树索引:

在每个数据页中选出ID最小的数据,并且只需要他们的主键ID以及他们所在页的页号,组成一个新的数据页。这个新的数据页跟之前的数据页没有太大区别,大小也是16K。为了区分跟之前数据页,新的数据页里需要加入页层级的信息,因此数据页里面就有了上下层级的概念(B+树),最下面一层是叶子节点、其他都是非叶子节点。

 当我们需要查找一条数据的时候,会先查找非叶子节点,然后根据非叶子节点定位到具体的叶子节点。(比如:我们要查找ID=2数据的时候,会现在非叶子节点里面找,发现向左最小ID是1向右最小ID是4,如果ID是2的数据存在,哪一顶是在页号100中,在到页号100中查找id为2的数据)。

上面举例的是两层的数据结构,如果是3层、可以通过类似的方法在构建一层,就成了三层的树。值得注意的是,上面的数据页的页号并不是连续的,在磁盘里面页不一定是挨在一起的,如果查询过程中两个页都在磁盘中 那么最多可能需要经历2次的磁盘IO,才能加载到内存。

-----------------------------2000w的说法是怎么来的------------------------------

假设非叶子节点指向其它数据页的数据量为x,叶子节点里面存放数据为y,层级为z,那么这个b+树可以存放的数据总量为

---首先看下x的数据怎么算的,假设非叶子节点掐头去尾可以存放15k的数据,而每一行有主键和页号组成,假设主键是bigint大小是8byte,,页号在源码叫FIL_PAGE_OFFSET,大小4byte(字节),那么非叶子节点的一条数据就是12字节左右,15k/12Byte = 1280,也就是说x=1280。

---在来算一下y的值,叶子节点和非叶子节点数据接口是一样的,所以假设掐头去尾剩15k可以存放数据,而叶子节点存放的是真正的数据,假设一行数据站1k,哪一个数据页能存放15行,也就是y=15。

回到上面的计算公式:

 所以说这个2000w就是我们常说的建议值,如果说在加一层,哪数据就有点多了,三层数据页对应最多3次磁盘IO,是比较合理的。

那么假设数据超过2000w就会慢吗:

上面说的是一行数据为1k的情况下,但是如果我一行存放数据更小呢,比如只用了250Byte,那么单个数据页就能存放60行数据,那同样是三层的数据结构,单表支持的行数据就能到1个亿。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值