B树/[oracle]connect BY语句

读大神的书,出现不少没有见过的函数和便捷操做,特此记录html

connect by 以前没有接触过,为了学习这个语句,先了解一下B树数据类型是最好的方法。算法

【本人摘自如下博客】数据库

https://www.cnblogs.com/George1994/p/7008732.html数据结构

https://www.cnblogs.com/mushroom/p/4100087.html函数

https://www.cnblogs.com/vincently/p/4526560.html学习

简介

这里的B树,也就是英文中的B-Tree,一个 m 阶的B树知足如下条件:spa

  1. 每一个结点至多拥有m棵子树;
  2. 根结点至少拥有两颗子树(存在子树的状况下);
  3. 除了根结点之外,其他每一个分支结点至少拥有 m/2 棵子树;
  4. 全部的叶结点都在同一层上;
  5. 有 k 棵子树的分支结点则存在 k-1 个关键码,关键码按照递增次序进行排列;
  6. 关键字数量须要知足ceil(m/2)-1 <= n <= m-1;

【另外一种描述,换种写法,意思同样:指针

根据这张图介绍下b树的基础定义:code

这是颗5阶B树的图,阶简写m。htm

    1:树中每一个结点最多含有m个子节点(m>=2)。 

    2:每一个内节点至少 [ceil(m / 2)] 个子节点。  内节点即非根节点非页子节点,也能够叫中间节点。

    3: 关键字key的数量   [ceil(m / 2)-1]<= n <= m-1,关键字按递增排序。

    6: 每一个叶节点具备相同的深度,即树的高度h,并且不包含关键字信息。

上图也可称为最小度数为3的b树,(degree) ,简写t。  

              t实际上是上面第二条定义中 [ceil(m / 2)] 的值,即t=[ceil(m/2)], 3=ceil(5/2) 。 

    1:每一个非根节点至少有t-1个关键字,非根内节点至少有t个子节点。 t称为度数(degree),t>=2  。

 .  2:每一个节点至多有2t-1关键字,每一个内节点最多有2t个子节点。

    3:每一个叶节点具备相同的深度,即树的高度h,并且不包含关键字信息。

度和阶都是描述子节点的数量的。

算法导论译版中是用度来描述的。

数据结构与算法分析是用阶来描述,网上大多也是。

end】

这是B树存储在硬盘的逻辑结构图。

其中根节点中17,35在称为关键字(key) ,实际中每每附带更多复杂类型数据。

能够看出一个节点包含 keys  ChildNotePointer  2部分信息。

操做

既然是树,那么必不可少的操做就是插入和删除,这也是B树和其它数据结构不一样的地方,固然了,还有必不可少的搜索,分享一个对B树的操做进行可视化的网址,它是由usfca提供的。

假定对高度为h的m阶B树进行操做。

插入

新结点通常插在第h层,经过搜索找到对应的结点进行插入,那么根据即将插入的结点的数量又分为下面几种状况。

  • 若是该结点的关键字个数没有到达m-1个,那么直接插入便可;
  • 若是该结点的关键字个数已经到达了m-1个,那么根据B树的性质显然没法知足,须要将其进行分裂。分裂的规则是该结点分红两半,将中间的关键字进行提高,加入到父亲结点中,可是这又可能存在父亲结点也满员的状况,则不得不向上进行回溯,甚至是要对根结点进行分裂,那么整棵树都加了一层。

其过程以下:

 

 

删除

一样的,咱们须要先经过搜索找到相应的值,存在则进行删除,须要考虑删除之后的状况,

  • 若是该结点拥有关键字数量仍然知足B树性质,则不作任何处理;
  • 若是该结点在删除关键字之后不知足B树的性质(关键字没有到达ceil(m/2)-1的数量),则须要向兄弟结点借关键字,这有分为兄弟结点的关键字数量是否足够的状况。
    • 若是兄弟结点的关键字足够借给该结点,则过程为将父亲结点的关键字下移,兄弟结点的关键字上移;
    • 若是兄弟结点的关键字在借出去之后也没法知足状况,即以前兄弟结点的关键字的数量为ceil(m/2)-1,借的一方的关键字数量为ceil(m/2)-2的状况,那么咱们能够将该结点合并到兄弟结点中,合并以后的子结点数量少了一个,则须要将父亲结点的关键字下放,若是父亲结点不知足性质,则向上回溯;
  • 其他状况参照BST中的删除。

其过程以下:

B+树

为何要B+树

因为B+树的数据都存储在叶子结点中,分支结点均为索引,方便扫库,只须要扫一遍叶子结点便可,可是B树由于其分支结点一样存储着数据,咱们要找到具体的数据,须要进行一次中序遍历按序来扫,因此B+树更加适合在区间查询的状况,因此一般B+树用于数据库索引,而B树则经常使用于文件索引。

简介

一样的,以一个m阶树为例:

  1. 根结点只有一个,分支数量范围为[2,m];
  2. 分支结点,每一个结点包含分支数范围为[ceil(m/2), m];
  3. 分支结点的关键字数量等于其子分支的数量减一,关键字的数量范围为[ceil(m/2)-1, m-1],关键字顺序递增;
  4. 全部叶子结点都在同一层;

操做

其操做和B树的操做是相似的,不过须要注意的是,在增长值的时候,若是存在满员的状况,将选择结点中的值做为新的索引,还有在删除值的时候,索引中的关键字并不会删除,也不会存在父亲结点的关键字下沉的状况,由于那只是索引。

B树和B+树的区别

这都是因为B+树和B具备这不一样的存储结构所形成的区别,以一个m阶树为例。

  1. 关键字的数量不一样;B+树中分支结点有m个关键字,其叶子结点也有m个,其关键字只是起到了一个索引的做用,可是B树虽然也有m个子结点,可是其只拥有m-1个关键字。
  2. 存储的位置不一样;B+树中的数据都存储在叶子结点上,也就是其全部叶子结点的数据组合起来就是完整的数据,可是B树的数据存储在每个结点中,并不只仅存储在叶子结点上。
  3. 分支结点的构造不一样;B+树的分支结点仅仅存储着关键字信息和儿子的指针(这里的指针指的是磁盘块的偏移量),也就是说内部结点仅仅包含着索引信息。
  4. 查询不一样;B树在找到具体的数值之后,则结束,而B+树则须要经过索引找到叶子结点中的数据才结束,也就是说B+树的搜索过程当中走了一条从根结点到叶子结点的路径。

 

CONNECT BY PRIOR

这个子句主要是用于B树结构类型的数据递归查询,给出B树结构类型中的任意一个结点,遍历其最终父结点或者子结点。

先看原始数据:

复制代码
 1 create table a_test
 2 ( parentid varchar2(10),
 3   subid    varchar2(10));
 4 
 5 insert into a_test values ( '1', '2' );
 6 insert into a_test values ( '1', '3' );
 7 insert into a_test values ( '2', '4' );
 8 insert into a_test values ( '2', '5' );
 9 insert into a_test values ( '3', '6' );
10 insert into a_test values ( '3', '7' );
11 insert into a_test values ( '5', '8' );
12 insert into a_test values ( '5', '9' );
13 insert into a_test values ( '7', '10' );
14 insert into a_test values ( '7', '11' );
15 insert into a_test values ( '10', '12' );
16 insert into a_test values ( '10', '13' );
17 
18 commit;
19 
20 select * from a_test;
复制代码

 

对应B树结构为:

 


 

接下来看一个示例:

要求给出其中一个结点值,求其最终父结点。以7为例,看一下代码

start with 子句:遍历起始条件,有个小技巧,若是要查父结点,这里能够用子结点的列,反之亦然。

connect by 子句:链接条件。关键词prior,prior跟父节点列parentid放在一块儿,就是往父结点方向遍历;prior跟子结点列subid放在一块儿,则往叶子结点方向遍历,

                         parentid、subid两列谁放在“=”前都无所谓,关键是prior跟谁在一块儿。

order by 子句:排序,不用多说。

--------------------------------------------------

下面看看往叶子结点遍历的例子:

这里start with 子句用了parentid列,具体区别后面举例说明。

connect by 子句中,prior跟subid在同一边,就是往叶子结点方向遍历去了。由于7有两个子结点,因此第一级中有两个结果(10和11),10有两个子结点(12,13),11无,因此第二级也有两个结果(12,13)。即12,13就是叶子结点。

 





 

 

下面看下start with子句中选择不一样的列的区别:

以查询叶子结点(往下遍历)为例

结果很明显,原意是要以7为父结点,遍历其子结点,左图取的是父结点列的值,结果符合原意;右图取的是子结点列的值,结果多余的显示了7 的父结点3.

---------------------------------------

关于where条件的语句,之后验证后再记录。先留个疑问

 

相关文章
相关标签/搜索