1.什么是B+树
B+树是对B树的优化和变形,也是一种多路搜索树,其定义和B-树基本相同,差别如下:
-
每个节点中关键字的数量和孩子数量相等,相当于取消了B树最左边的左孩子
- 根节点的关键字数量为[1,M]
- 非根节点关键字数量为[M/2,M]
-
所有的值(kv)都会出现在叶子节点上,并且所有的叶子节点都会用一个指针链接起来(方便遍历),因此只需要遍历叶子节点即可。非叶子节点中只保存key,相当于路径索引。父亲中的存的key是由孩子中的最小值组成
-
B+树的搜索与B-树基本相同,区别是B+树只有达到叶子节点才能命中(B-树可以在非叶子节点中命中),其性能也等价于在关键字全集做一次二分查找。
2.B+树的特性
- 所有关键字都出现在叶子节点中, 不可能在非叶子节点中命中
- 每个节点中的孩子数和关键字数相等
- 一个节点中的关键字数量按照升序排列
- 非叶子节点相当于是叶子节点的索引,叶子节点相当于是存储数据的数据层
- 节点数达到M+1时再进行分裂出一个兄弟节点,拷走一半的数据。往父亲中插入一个关键字和一个孩子,关键字就是兄弟节点中的第一个字,孩子就是兄弟节点
3.B+树的插入过程
M=3,需要插入5,6,4,8,7,10,36,16
4.B+树查找的优点
-
B+树的优势主要体现在查询性能上
-
B-树的每个节点都有卫星数据(索引元素指向的数据记录),B+树中间节点没有卫星数据,这就意味着同样大小的磁盘页,B+树可以容纳更多的节点 -> B+树比B-树更加的矮胖,即IO的次数更少
-
性能上B+树也更加稳定,因为B-树只需要找到匹配元素即可,B+树必须查询到叶子节点
-
范围查询更便捷,
5.B*树
B*树是B+树的变形,在B+树的非根和非叶子节点再增加指向兄弟节点的指针
- B树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3(代替B+树的1/2);
- B*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了)
- 如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针。 所以,B * 树分配新结点的概率比B+树要低,空间使用率更高
- B*树主要就是节省空间
6.小结
-
B-树:多路搜索树,每个结点存储M/2-1到M-1个关键字,非叶子结点存储指向关键字范围的子结点;所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中
-
B+树:在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中
-
相对于B树,B+树适合文件索引系统
- B+树空间利用率更高,因为B+树的内部节点只是作为索引使用,而不像B-树那样每个节点都需要存储硬盘指针
- 增删文件(节点)时,效率更高,因为B+树的叶子节点包含所有关键字,并以有序的链表结构存储,这样可很好提高增删效率
-
B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率从1/2提高到2/3,提高了空间的利用率
7.数据库和B+树的关系
- 建表的时候,服务器会先解析sql语句,那么每一张表都会对应一棵B+树,表中的主键就是B+树的key(唯一的)
- 利用主键进行查找,即利用B+树的特性进行查找,是非常快的
- 如果非主键查找,就需要遍历整棵树,效率就会下降,不过相对于B树来说,B+树还是块的,直接从叶子节点开始找即可,B树还需要进行层序遍历
- 如果非主键查找想要变快,可以针对查找的值建立索引,重新建立一棵B+树或者哈希表
8.Mysql两种引擎
8.1MyISAM
-
MyISAM引擎是MySQL5.5.8版本之前默认的存储引擎,不支持事务,支持全文检索,使用B+树作为索引结构,叶节点的data域存放的是数据记录的地址
-
事务
假设有事件 A转账给B 第一条语句:A-1万元 第二条语句:B+1万元 如果其中一条语句失败,就会出现问题,这时就需要事务 => 执行两条sql语句之前,开启事务 执行两条sql成功,则提交事务 失败,则回滚事务
-
MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。下图是MyISAM索引的原理图:
-
这里设表一共有三列,假设我们以Col1为主键,则图8是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址
-
在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。如果我们在Col2上建立一个辅助索引,则此索引的结构如下图所示:
-
MyISAM的索引方式也叫做“非聚集”(叶子节点存储的是地址,数据是分离的)的,之所以这么称呼是为了与InnoDB的聚集索引区分
8.2InnoDB
- InnoDB存储引擎,支持事务,其设计目标主要面向在线事务处理的应用,从MySQL数据库5.5.8版本开始,InnoDB存储引擎是默认的存储引擎。InnoDB支持B+树索引、全文索引、哈希索引。但InnoDB使用B+Tree作为索引结构时,具体实现方式却与MyISAM截然不同
- 第一个区别是InnoDB的数据文件本身就是索引文件。MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址InnoDB索引,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引
- 第二个区别是InnoDB的辅助索引data域存储相应记录主键的值而不是地址,所有辅助索引都引用主键作为data域
- 聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录
- 最大区别:MyISAM不支持事务,InnoDB支持事务
- 上左图是InnoDB主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。
- 与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域(上右图)
参考文章链接:
链接1