B-Tree
简介
B-Tree也是一种自平衡的搜索树,但是与许多其他自平衡的搜索树不同的是:
- 其他自平衡树(AVL、RB Tree)都是假设所有数据都存储在主存中。
- B-Tree考虑的是==访问磁盘数据==的情况。
试想一下淘宝、拼多多等上亿的用户数据如果都放在主存中,那必然会出问题。主存是在运行时为运算提供数据的存储服务的,最优的方式应该是运算需要什么主存就存储什么;而磁盘才应该用于保存所有的数据,供主存按需取用。
磁盘的访问时间开销相比起主存要大得多,而B-Tree的一个主要目的就是尽量减少访问磁盘的次数。磁盘的IO有一个特点,就是以==块==为单位,所以从磁盘读取1B的数据和读取一个块大小的数据消耗的时间基本相同。所以B树是一种胖树,把尽可能多的数据存储在一个结点中,这样就提高了每一次IO的数据利用率,同时结点变胖降低了树的整体高度。故往往设置一个结点的大小就等于一个磁盘==数据块==大小。这就有点像一次最多能够存多少就存多少的感觉。
B-Tree的性质
对于一棵M阶的B树:
- 树中的每一个结点最多有M个子树,也即当前结点最多包含M-1个key值;
- 根结点若非叶子结点,则至少含有2个子树;
- 除了根结点,所有非终结点至少含有M/2个子树;
- 所有叶子结点都在同一个层次上。
B-Tree的插入
- 通过查找,找到要插入的结点;
- 将key值插入结点,维护结点大小:若结点大小超过M-1,则分裂出一个父节点。
由此可见B-Tree的增长有些类似哈夫曼树,不断生出一个父结点,故==B-Tree是自底向上增长的==。
B+树
B+树是B树的一个升级变种,其与B-树的主要区别就在于:
- B+树分支结点存储的是索引,不存储数据;
- B+树叶子仅用于存储数据(数据指针);
- 叶子节点还有一个指向其相邻叶子的指针。
由于B+树的分支结点存储的是索引地址,所以相比起B树用结点存储数据,==B+树同样大小的结点能够容纳更多的索引==。这样整个B+树的高度降低,在查找数据的时候就能够减少磁盘IO。
其次,真正存储数据的叶子结点利用地址连接,类似链表,而这个链表整体就是有序的,故==适合进行范围查找==。正因如此MySQL的索引使用的就是B+树,充分发挥了其单个查找、范围查找的能力。