(2)所以当你用红黑树的时候,你一次只能得到一个键值的信息,而用B树,可以得到最多M-1个键值的信息。这样来说B树当然更好了。 假定操作系统一次读取一个节点,并且根节点保留在内存中,那么B树在100万个数据中查找目标值,只需要读取两次硬盘。B 树可以看作是对2-3查找树的一种扩展,即他允许每个节点有M-1个子节点。 M/2个子节点 ; 所有叶子节点都在同一层 。 四、B树与B+树的对比 B和B+树的区别在于,B+树的非叶子结点只包含导航信息,不包含实际的值,所有的叶子结点和相连的节点使用链表相连,便于区间查找和遍历。 2、B+树的优点 由于B+树在内部节点上不好含数据信息,因此在内存页中能够存放更多的key。 数据存放的更加紧密,具有更好的空间局部性。
引言 时隔一年,我又想起当初看数据库时,看到的B+树,就是数据库的索引使用的数据结构。再整理一下,看看自己没有忘记很多吧。 概述 B+树之前,先来看一下二叉查找树(1,2,3,4,5,6,7) ? 但想想数据库查找数据的场景: select * from user where id > 10, 显然,对于这种查找区间来说,二叉查找树并不高效。那么B+树是如何解决这个问题的呢? 这时,如果想找select * from user where id > 2 and id < 5, 那么,直接找到2的下标,然后向后遍历,到第一个>=5的值出现停止,之间是满足条件的数据。 没错,这就是B+树。 这个结构是怎么想出来的我不知道啊,但是我今天突然发现,他的存储方式和跳表十分之像啊。莫非是受到了跳表的启发?亦或是跳表受到了B+树的启发?咱也不知道。 B+树是不是分叉越多越好 那肯定不是越多越好啊,要是一层就把所有数据都存储了,要他还有什么用,根本没有起到快速定位的作用。 但我想说的并不是这。
B树和B+树都是用于外查找的数据结构,都是平衡多路查找树。 两者的区别 在B+树中,具有n个关键字的结点含有n棵子树,即每个关键字对应一颗子树;而在B树中,具有n个关键字的结点含有(n+1)棵子树。 在B+树中,除根节点外,每个结点中的关键字个数n的取值范围是[m/2]~m,根节点n的取值范围是2~m;而在B树中,除根节点外,其他所有非叶结点的关键字个数n的取值范围是[m/2]-1~m-1,根节点n B+树中的所有叶结点包含了全部关键字,即其他非叶结点中的关键字包含在叶结点中;而在B树中,关键字是不重复的。 B+树中的所有非叶结点仅起到索引的作用,即结点中的每个索引项只含有对应子树的最大关键字和指向该子树的指针,不包含该关键字对应记录的存储地址;而在B树中,每个关键字对应一个记录的存储地址。 通常在B+树上有两个头指针,一个指向根节点,另一个指向关键字最小的叶结点,所有叶结点链接成一个不定长的线性链表,所以B+树可以进行随机查找和顺序查找;而B树只能进行随机查找。
目前常见的主要的三种存储引擎是:哈希、B+树、LSM树。LSM下次再说,hash讲过了。 没有什么B-树,那是 B-tree,国内一直翻译成B-树,其实就是B树。 B树我也不想说了,因为已经被升级过了,叫B+树。 下图来自 小灰的算法之旅,懂得人自然就懂了: ---- 对比一下B树: 这个是B树。 ---- B+树对于B树的改进 1、所有数据都在叶子节点。算法更容易理解了。回头抽空手写一下B+树,正好跳表也要重写了。 2、底层叶子节点使用链表串起来了。 这第二个改进不可谓不秀。 单这么看自然是不明所以的,但是凡事都要放在上下文中去看,B+树的上下文对应的就是磁盘IO的索引呐,那如果我要范围查询呢?比如说我要上面树里面 4-10 的所有数据,B 树怎么作为?B+树怎么作为?
B树、B+树的区别及MySQL为何选择B+树 1. B树和B+树的定义 B树和B+树都是一种多路搜索树,常用于数据库和文件系统中进行索引操作。在介绍B树和B+树的区别之前,先来了解一下它们的定义。 B树 B树是一种平衡查找树,其每个节点最多包含k个孩子,k称为B树的阶。除根节点和叶子节点外,其它每个节点至少有ceil(k/2)个孩子,即一个节点可以拥有的关键字数在ceil(k/2)和k之间。 B树满足以下条件: 根节点至少有两个孩子。 每个节点最多有k个孩子。 除根节点和叶子节点外,其它每个节点至少有ceil(k/2)个孩子。 所有叶子节点都在同一层。 B+树 B+树也是一种多路搜索树,与B树相似,但在B+树中,所有的数据都存储在叶子节点中,而非在非叶子节点中。B+树满足以下条件: 所有关键字都出现在叶子节点的链表中,且链表中的关键字恰好是有序的。 2. B树和B+树的区别 B树和B+树虽然都是多路搜索树,但它们的区别还是比较明显的。 存储结构 B树的非叶子节点中既包含索引,也包含数据,而B+树的非叶子节点中只包含索引,数据都存储在叶子节点中。
先剔除掉范围查询的情况,原因 1、2、6 可以通过红黑树来解决,那么其实就剩下 2 个原因: I/O 次数对比; 磁盘预读功能的利用; 4. 对于红黑树而言,其 I/O 次数近似为 log2(n),为什么是近似呢? B/B+树的索引数量 B 树的节点中存储:指针、关键字(主键)、数据 B+ 树的非叶子节点:指针、关键字 B+树的叶子节点:指针(链表)、关键字、数据 注意,这里不是绝对的,比如有的 B+ 树中叶子节点存储的不是数据 而且上述是假设数据为 1KB,如果数据没那么大,高度为 3 的 B 树能存储更多的数据,但是如果用在大型数据库索引上还是不够。 B+ 树: B+树 如上图,B+树的核心在于非叶子节点不存储数据。 B/B+树的优点 更适合磁盘存储,减少了树的层级,进而减少 I/O 次数; B 树和 B+ 树对比 都是 B 树,但是 B+树更适合范围查询,比如 Mysql,且查询次数很稳定,为 logn。
1.减少磁盘的IO 2.更快的搜索算法 操作系统中, 管理内存是按照页page 4K 管理的 管理磁盘是按照block 16K 现在有n = 1000w个索引需要从磁盘中进行读取和搜索? avl树和m为300的B-树? avl树的高度:log2n = 24层 最差的情况一个节点只存储一个索引? 最差需要24次磁盘IO B-树高度:log(300)n = 3 层 最多花费3次磁盘IO B+树 B+树是B-树的一种变形 非叶子结点只存储索引,不存储数据 B+树的叶子结点包含全部的关键字信息 ,而B-树的数据分散在各个结点当中。 B+树存放的索引项相对于B-树能够存储的更多。 B*树 B*树是B+树的变体,在B+树的非根和叶子结点在增加指向兄弟结点的指针 B*提高了结点的利用率。
这就是B+树的原理,但是写起来就很糟糕,因为会产生大量的随机IO,磁盘寻道速度跟不上。 关于b树 B+树最大的性能问题是会产生大量的随机io。随着新数据的插入,叶子节点会慢慢分裂。 例如,Oracle 的常用索引使用 B+ 树。下面是一个B+树的例子 根节点和分支节点很简单,记录每个叶子节点的最小值,用指针指向叶子节点。 关于lsm树 LSM 树本质上是读写之间的平衡。与B+树相比,它牺牲了部分读取性能来提高写入性能。 读取的时候,因为我们不知道数据在哪棵树上,所以必须遍历所有的树,但是每棵树中的数据都是有序的。 以上就是LSM树最本质的原理,有了原理,再看具体的技术就很简单了: 关于lsm内存结构,可以是B+树,还可以为跳跃表(skip-list)或是一个有序字符串表(SSTables)。
先剔除掉范围查询的情况,原因 1、2、6 可以通过红黑树来解决,那么其实就剩下 2 个原因: I/O 次数对比; 磁盘预读功能的利用; 4. 对于红黑树而言,其 I/O 次数近似为 log2(n),为什么是近似呢? B/B+树的索引数量 B 树的节点中存储:指针、关键字(主键)、数据 B+ 树的非叶子节点:指针、关键字 B+树的叶子节点:指针(链表)、关键字、数据 注意,这里不是绝对的,比如有的 B+ 树中叶子节点存储的不是数据 而且上述是假设数据为 1KB,如果数据没那么大,高度为 3 的 B 树能存储更多的数据,但是如果用在大型数据库索引上还是不够。 B+ 树: B+树 如上图,B+树的核心在于非叶子节点不存储数据。 B/B+树的优点 更适合磁盘存储,减少了树的层级,进而减少 I/O 次数; B 树和 B+ 树对比 都是 B 树,但是 B+树更适合范围查询,比如 Mysql,且查询次数很稳定,为 logn。
B树、B+树、B*树——简单介绍 强烈推介IDEA2020.2破解激活,IntelliJ 如果允许每个节点可以有更多的数据项和更多的子节点,就是多叉树; 【2】2-3树,2-3-4树就是多叉树,多叉树通过重新组织节点,减少树的高度,能对二叉树进行优化。如下图就是一个2-3树; ? 2-3 树基本介绍:最简单的 B树结构,具有如下特点: ■ 2-3 树的所有叶子节点都在同一层(只要是B树都满足这一点); ■ 有两个子节点的叫二节点,二节点要么没有子节点,要么有两个子节点 三、B树、B+树、B*树 ---- 【1】B树介绍:前面介绍的2-3、2-3-4树就是 B树,在 MySql 中经常听说某种索引是基于 B树、B+树的,如下图: ? 【2】B+树介绍:B+ 树是B树的变体,也是一种多路搜索树,如下图: ? 【3】B* 树介绍:B* 树是B+树的变体,在B+树的非根和非叶子节点增加了指向兄弟的指针,如下图: ?
M/2的结点;删除结点时,需将两个不足M/2的兄弟结点合并; B+树 B+树是B-树的变体,也是一种多路搜索树: 1.其定义基本与B-树同,除了: 2.非叶子结点的子树指针与关键字个数相同 4.更适合文件索引系统; B*树 是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针; ? B*树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3(代替B+树的1/2); B+树的分裂: 当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点 B+树要低,空间使用率更高; 小结 B树:二叉树,每个结点只存储一个关键字,等于则命中,小于走左结点,大于走右结点; B-树:多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点 ; B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率从1/2提高到2/3;
具体区别1、叶子节点B树不存指针,B+树存双向指针,方便范围查找2、B树非叶子节点也存储数据,B+树不存储数据3、B树不会有冗余索引,是唯一的,B+树会有冗余索引4、存放同样的数据,B树的层级比B+树要高 ,因为B+树有冗余索引,所以相同层级的叶子节点的数据就会更多,(可以有更多的分叉)索引:如果存在主键,主键索引就是聚集索引如果不存在主键,将使用第一个唯一(UNIQUE)索引作为聚集索引。
定义 参考百度百科及wiki百科定义:B +树是一个N叉排序树,每个节点通常有多个孩子,一棵B+树包含根节点、内部节点和叶子节点。 B+ 树元素自底向上插入。 另外说明的一点,B+中的B并不是代表二叉(Binary),而是代表平衡(Balance)。 对于m阶B+树,m的值越大,固定高度的B+树存放的值就越多。 举个例子,假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一棵9阶B-tree(一个结点最多8个关键字)的内部结点需要2个盘块。 而B+树内部结点只需要1个盘块。当需要把内部结点读入内存中的时候,B 树就比B+树多一次盘块查找时间(在磁盘中就是盘片旋转寻道的时间)。
常见多叉树: (1). 2-3树: 第二层左边的节点,有两个元素,7和5,它又有3个子节点,这就叫做2-3树,其中节点7 5称为3节点,节点9称为2节点。 ? (2). 2-3-4树: 和2-3树的区别就是,它还允许节点有三个元素且有四个子节点。 4. B树: B是balance,平衡的意思,所以,B树首先是一棵平衡树,而平衡树首先得是一棵排序数。 B+树: B+树是B树的变体,和B树的区别就是,B+树所有数据都存放在叶子节点。 B+树所有的数据都存放在叶子节点的链表中,且链表中的数据也是有序的; 非叶子节点中存放的是索引,而不是要操作的数据,每个非叶子节点都会存放叶子节点的索引,也叫稀疏索引; B+树要进行搜素时,从根节点开始 B+树一般用于文件系统; 6. B*树: B*树又是B+树的变体,就是在B+树的基础上,在非根非叶子节点之间增加了指向兄弟节点的指针。
上图就是一棵B+树,每个部分有3个主要概念:物理磁盘块、数据项(蓝色)、指针(红色) 如磁盘块1,包含数据项 17、35,包含指针 P1、P2、P3,P1指向小于17的磁盘块,P2指向在17和35之间的磁盘块 真实的数据存于叶子节点中,即 3、5、9、10、13、15、28、29、36、60、75、79、90、99 非叶子节点中并不存放真实数据项,只存放指引搜索方向的数据项,如 17、35 并不真实存在于数据表中 B+ 树查找过程 如果要查找数据项29 1. 在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,通过P2指向的磁盘地址,把磁盘块3由磁盘加载到内存,发生第二次IO 3. 29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块 内存中做二分查找找到29,结束查询 总计三次IO,即可找到目标数据项 3层的B+树可以表示上百万的数据,对查询性能的提高是巨大的
阶数与节点容量B+树的阶数m决定了节点的子节点数量和键值容量,通常与磁盘页大小对齐以优化I/O 非根节点:键值数范围:⌈m/2⌉−1≤k≤m−1⌈m/2⌉−1≤k≤m−1(如3阶B+树,非根节点最多2个键值 与B树的区别B+树在以下方面区别于B树 数据存储位置:B树内部节点存数据,B+树仅叶子节点存数据。链表结构:B+树叶子节点通过链表连接,B树无此设计。 一棵B+树可以存放多少行数据? 对于叶子节点,如果一行数据大小为1k,那么一页就能存16条数据;高度为2的B+树(18720 条数据)根节点存储索引指针节点,那么它有1170个叶子节点存储数据,每个叶子节点可以存储16条数据,一共 1170 B-Tree,叶子节点和非叶子节点都保存数据,相同的数据量,B+树更矮壮,也是就说,相同的数据量,B+树数据结构,查询磁盘的次数会更少。
要是那个人说b树和b-树不一样 那你可以认为他是zz了hh,b树就是b-树 说起来b树的发明主要是为了减少磁盘io操作 将树的结构设计成矮胖型而不是瘦高型,因为数据库索引是存储在磁盘上的,当数据量比较大时 2.每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m 3.每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m 4.所有的叶子结点都位于同一层。 一个m阶的B+树具有如下几个特征: 1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。 2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。 3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。 下图是一个b+树( b-树改造加链表) ?
说明:本文从B树开始谈起,然后论述B+树、B*树,最后谈到R 树。其中B树、B+树及B*树部分由weedge完成,R 树部分由Frankie完成,全文最终由July统稿修订完成。 (2/3)*M,即块的最低使用率为2/3(代替B+树的1/2)。 B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针。 7.总结 通过以上介绍,大致将B树,B+树,B*树总结如下: B树:有序数组+平衡多叉树; B+树:有序数组链表+平衡多叉树; B*树:一棵丰满的B+树。 Bucket Li:"mysql 底层存储是用B+树实现的,知道为什么么。内存中B+树是没有优势的,但是一到磁盘,B+树的威力就出来了"。
B+树的叶子节点由一条链相连,而B树的叶子节点各自独立。 使用B+树的好处 由于B+树的内部节点只存放键,不存放值,因此,一次读取,可以在内存页中获取更多的键,有利于更快地缩小查找范围。 2.B树遍历整个树的过程和二叉树本质上是一样的,B树相对二叉树虽然提高了磁盘IO性能,但并没有解决遍历元素效率低下的问题。 针对以上两个问题,B+树诞生了,B+树相比B树,本质上是一样的,区别就在与B+树的所有根节点都不带有任何数据信息,只有索引信息,所有数据信息全部存储在叶子节点里,这样,整个树的每个节点所占的内存空间就变小了 那么,我们最后再总结一下B+树的优点: (1) B+树的磁盘读写代价更低 B+的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B树更小。 (2)B+树的数据信息遍历更加方便 B+树只要遍历叶子节点就可以实现整棵树的遍历,而B树不支持这样的操作(或者说效率太低),而且在数据库中基于范围的查询是非常频繁的,所以数据库索引基本采用
B树的产生是为了: 解决因为大量数据时,红黑树/二叉查找树的深度太深,如数据库的索引数据存放在磁盘上,而如果使用红黑树的话,深度太深,每一个查找一个节点都需要寻道+磁盘读写