聊聊樹狀結構如何在數據庫中存儲
昨天有人在QQ小組問起,無限分層的樹狀結構,數據量比較大,在一萬條以上,如何設計數據庫的結構。其實這是個老生常談的問題,一般的做法是有一個 pid字段,為了提高效率,還會有個FullPath字段。(一些人還設置一個層級字段,但我不知道這個字段有何作用),FullPath字段可以用 id-id-id….這種方式拼字符串存儲,這樣可以方便地用 like 語句進行查詢某個節點及其子節點。
曾經看到過另外一種存儲方式,利用了一般樹結構可以轉換二叉樹的這一做法,用二叉樹進行存儲,在數據量大的情況下,存儲讀效率比上述的常見方案更優些,所以特寫此文簡單介紹一番。
下圖說明了這種方案
如圖所示,在每個節點上,有left ,right兩個字段,我們看到,圖上從根節點順著子節點開始畫一條線,每深入一層left加一,到底后,right=left+1,然后順著節點回溯,right逐級加一,一直回到根節點。
如果要查詢某個節點及其子節點,比如 fruit 節點 ,條件為 where left between 2 and 11
要查某個節點的full path ,比如 banana,條件為 where left<8 and right >9
如果要插入某個節點,比如red yellow直接插入一個節點,則update left =left+2 where left>=7 ,update right=right+2 where right>7,然后 新節點的left rigt分別是 7,8。 刪除節點類似。
這種方式,因為id都是int型數據,加上索引后,讀的效率較高。而fullPath字段的方案查詢時候用的是字符串操作like,效率較低。
在內存中,如果要還原樹狀結構,即在每個節點上增加pid屬性和children屬性,則稍微麻煩些,可以如下操作:
- 按left between x and y order by left 取數據
- 順序遍歷數據,如果left=上一個Left+1,則是上一個節點的子節點,設置兩個對象的父子關系,如果發生跳號,則是上一個節點的兄弟節點。
OK,大致的方案就介紹到這里
原文鏈接:http://www.cnblogs.com/honghuamin/archive/2011/07/24/2115635.html
【編輯推薦】