赞
踩
假设有一张user表,其中id是主键
user表: |
id | name | age |
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个亿。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。