我们这里以InnoDB存储引擎为例。首先我们看一张图。
这个就是B+树了。 如果对于之前没接触过,或已经忘了的同学。乍一看这图,心里想这啥玩意哦。二叉树搜索树知道吧,这个就是基于他迭代过来的。我们首先来熟悉几个名词的概念接下来就会围绕这几个名词来讲。数据页,目录页,数据项,目录项,页目录。这些词都是我自个觉得我方便理解取得,如果到时候你觉得你用其他词更好理解也可以换。 首先我们要知道存储引擎将磁盘中的数据读取到内存中的基本单位是以页为基本单位,基本单位的概念不想过多解释。所以读取数据的只会是几页不会是几点几的情况。我这里把页又分为两种,一种是数据页,一种是目录页。但都是页这种结构,我喜欢这么区分而已。数据页顾名思义,存储的就是一条条数据项。目录页就是存储的一条条目录项。
疑问就来了,哪些页是数据页?哪些页是目录页呢?什么是数据项?什么又是目录项呢?
这些问题一个一个解决,看上面图,最下面的一行就是数据页,如果懂数据结构的,也知道这被称为叶子节点。之后我们就用专业术语了哈。 由此可知,叶子节点就是数据页,那么其他的非叶子节点 ,想必大家也清楚了,也就是目录页。
前两个问题解决了,现在看后两个问题。我们可以看到数据页中一列一列的就是数据项,目录页中一列一列的就是目录项。那么问题又来了,这数据项,目录项到底存储的什么,有什么作用。
接下来我们就解决这俩问题。
第一个问题,数据项中到底存储了什么。将就看看哈,数据项的第一个值就是有2,有0,有3,其实还有1。 这个值就代表了数据项的类型,2代表是最小数据项,0代表普通数据项,3代表最大数据项。还有一个1,1就代表普通目录项。这里判断最大最小是根据主键的值来判断的。
第二个空就是将各个数据项连接起来,数据项不是物理上连续的,是通过单链表实现的逻辑上的连续。至于为什么,不想多讲了。
第三个空就是主键字段了,第四个,第五个也是我们创建的字段。
到这儿了 相比大家对于数据项又有了进一步的认识。
第二个问题,目录项中的数据有哪些呢。
前面已经说了第一空和第二空的意思了,接下来我们说剩下的意义。 我们可以看到,第二个目录项的第一个存储的是主键值。第二个是该主键所在的页号,这里是存储的主键是对应页号的最小值。当我们查找主键为4的数据时,当判断到第二个时,比第五小,他就会去到第一个所对应的页号去找。当然真实的并不是单链表的这种遍历查找。接下来我们就会讲到底是如何进行快速查找的。
以上我们把B+树描述的差不多了,接下来就说说我觉得比较重要的内容。 仅仅是我觉得哈。咱就是说,页和页之间用的双链表,数据项与数据项用的单向链表,这要是正常的遍历查找数据,那还是麻烦呀。当然mysql肯定不会是这样子实现的撒。 这里就需要用到我们最开始提到的一个名词了,叫页目录。这个呢就是方便我们对数据进行查找。
页目录,每一个页中都有一个页目录,页目录实现的数据结构就是数组。如果我们将每一天数据的地址都存储在页目录中,再用二分法查找。其实效率也不是很高,因为在真实的开发中,数据肯定不止这么点。所以这里涉及到了一个分组的概念,几个几个数据项分为一组,把每一组中最大数据项的地址放在页目录中。那再用二分查找,那就能很快地进行定位到哪个组。再去遍历查找,就会很快了。
如何分组就是一个问题了,mysql把最小记录独自分为一组,之后每4-8条为一组,最后剩的和最大记录分为一组。
接下来补充个点。 B树和B+树区别,我们就说最大的区别。B+树只有叶子节点存储所有数据,非叶子节点只存储主键和页号(针对上面案例)。 B树无论是叶子节点还是非叶子节点,都会存储所有数据。这是他们最大的区别。