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條件的語句,之後驗證後再記錄。先留個疑問

 

相關文章
相關標籤/搜索