持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
上篇索引讲的基本上描述了索引的大概使用以及类型,本文来讲下索引的数据结构,众所周知目前MySQL索引的数据类型是B+TREE,如下图
这里我们抛出一个问题:为什么使用B+TREE树而不是B-TREE、链表、hash?
首先来推演下。我们都知道在MySQL中读取数据的时候是在内存中(数据页)操作的,而不是直接去读取磁盘,那样子效率太慢了,不直接读取磁盘不是不没有磁盘io(当然如果数据页中有那么不需要io操作,如果没有还是需要通过读取磁盘的数据到内存页的),数据页是一个双链表的结构,如果我们不知道当前数据在哪个数据页,那查找的时间复杂度是o(n),最坏的情况是遍历到最后一个数据页,这样子的查找时间是不能容忍的。所以这个时候索引出现了,(上篇说到索引本身就是为了加快查询的一种数据结构)。
根据上面的问题,我们可以知道如果数据是根据某种规律有序的,那么查找的时候是不是就可以使用二分查找法了?答案是正确的。二分查找法时间复杂度是2的对数。
在讲索引的数据结构之前,先简单说一下数据页,数据页是保存数据库记录的,可以有多条,如下图
由于需要保证有序,所以必须要有数据页必须要排序,根据什么排序?当然是主键索引,规则就是越往右主键索引越大,越往下主键索引越大,由于是双向链表每个数据页之间需要互通也就是left左边的数据页、right右边的数据页和next下一个数据页,所以给数据页新加了一个页码,用于数据页相互指向,如下图
key就是主键索引,右边的大于左边的,下边的大于上边的,但是大家注意到这里怎么还出现了一个目录项呢?
这里其实也就是B+tree和B-TREE的区别。
B-TREE每个数据页都存储索引数据和真实数据,这样子会导致树的高度相对较高,因为数据页的大小是有限的每条记录的大小决定了能够存储的条数,而B+TREE只有叶子结点存储真实数据,而非叶子节点只存储主键索引和目录项之间的关联,所以每一个非叶子节点都可以存储更多的主键索引也就是说大大减少了向下查找的次数变少了,向下查找的次数直接和磁盘io次数相关,所以B+TREE相对来说磁盘io次数更加少,但是不是说B+TREE查询速度一定比B-TREE快,因为B-TREE树每个节点都存储数据,如果数据就存在第一层叶子结点那B-TREE就可以直接返回数据了,反而B+TREE需要到叶子节点去获取数据。