2010-12-13 169 views
3

可能重複的樹木:
What is the most efficient/elegant way to parse a flat table into a tree?數據庫結構和查詢層次數據和數據

這我發現相當棘手的,並希望對此事的一些看法。 我想存儲分層數據(樹狀)與未知數量的層次和分支。我希望能夠隨時添加新的和刪除任何內容。

由於龐大的用戶羣,我需要能夠從層次結構中的任何節點一次查詢所有子級ID的查詢。

讓我們假設一個網站的家庭社交化和更新他們的地位,如Facebook在任何時候你可以查看家庭成員「牆」,其中還包括所有最近的狀態更新下面的人他們按照時間順序排列在層次結構中。

很顯然,一旦你擁有了這個家庭成員身份證的數組,這個家庭成員節點的子節點,獲取帖子在循環中很容易。

讓我們的例子簡單的表結構:

id | parentId | name 
________________________ 

1 | NULL | John 
2 |  1  | Peter 
3 |  1  | Bob 
4 |  3  | Emma 
5 |  2  | Sam 
6 |  4  | Gill 

等....你的想法。

我需要能夠做到以上這樣的東西,除非你認爲結構需要適應。我已閱讀mySql nested set model。 這看起來很複雜,如果有些東西不能正確更新並且會把所有東西搞砸,這可能是不可靠的。

我習慣於使用php和mysql,但一直在讀cassandra和節儉。不知道這是否會更容易?

+2

我知道它看起來很費勁,但嵌套集模型真的是你想要的。它很難解釋/描述這一點,而不是實現它,並且生成的SQL比螞蟻父子指針解決方案更簡單,性能更好 – 2010-12-14 01:34:04

回答

1

已經有很好的方法比您提出的解決方案更簡單。

下面是一些解釋如何做到這一點的鏈接(我們自己使用這個和你描述的很相似的問題,它工作的很好)。

這使得插入/更新更加複雜,但選擇所述樹結構的部分遠更快(只有一個查詢)。它允許在一個查詢中查找任何給定節點的所有子節點,並用一個查詢查找給定節點的所有祖先。

+0

嗨El Yobo,我意識到這種技術,我在我的帖子。謝謝你的頭,雖然和答案!如果你考慮一下,實際上只有一個查詢也是使用我提出的方法。因爲我需要的是一系列的孩子ID,所以我可以從其他表中找到相關的帖子信息。我不是嗎?我想獲得家庭成員的名字也是一個查詢......嗯......選擇......能夠添加數據和刪除對於我的應用程序非常重要,因爲它需要能夠處理大量數據每個層次結構,我不想冒「腐敗」的風險 – 2010-12-14 23:32:53

+0

進一步研究嵌套方法後,它需要一個額外的SQL查詢來檢索根節點的rgt和lft值。所以它正在分裂頭髮,就像我提出的方法一樣,沒有額外的步驟。此外,我會希望將rgt和lft的值從同一個表中的不同家族樹開始,這會增加我認爲由於附加的條件語句導致的進一步複雜性?這將是有點不守規矩,有超過10,000個節點。 – 2010-12-14 23:53:33

+0

啊,對不起,我沒有認出「嵌套模型」這個名字:)雖然它確實不是很費勁,第一次設置它的一點點工作,那就很好。上面的方法對我來說似乎要複雜得多。 – 2010-12-14 23:58:41

0

所以我想我已經想出了一個想法。

我反對嵌套集模型的原因是因爲它似乎仍然不是最好的方法,也不會是理想的性能解決方案。

我將介紹一個我一直在考慮的建議解決方案。 這個概念意味着創建一個hierarchal map表來跟蹤每個家庭成員/節點之間的所有關係。

它的工作方式是:

使用該映射表結構:

id | fMemberId | parentid 
===================================== 
1 |  3  |  2 
2 |  4  |  3 
3 |  4  |  2 

1)作爲一個新的家庭成員作爲父母的孩子,我們會採取建立父母ID並在我們的家庭成員表中創建一個新行,並設置父級ID以供未來額外的使用和功能使用。

2)在創建該行時,我們將創建新行,併爲新家族成員創建具有所有父ID的新行。

這樣做的一種快速方法是從新家庭成員中獲取父ID,然後對map表執行查詢,以查找家族成員ID與新家庭成員父ID相同的所有行然後將數組存儲在隨後的父ID中,並在map表中與新的家庭成員ID一起存儲。 這則僅需要一個SQL查詢搶佔了所有父ID的添加他們,而不是基於節點的數量大量查詢

當我們觀察一個家庭成員,這意味着飼料的職位,我們將能夠查詢數據庫中的map表中的行,以獲取當前系列成員的所有子代碼,然後在其他表中查找發佈數據。

主要的折衷是這類系統所需的潛在存儲量。 但是我相信閱讀速度會更快,因爲沒有條件SQL語句,並且也可能以這種方式快速寫入數據庫。

我們可以通過使用InnoDB的集羣ID分配一個初始的家族ID索引並根據家族ID創建一個帶有「下一個家庭成員ID」的新表來克服這個問題。

另外可靠性,如果一行沒有被寫入,就很容易添加它。它可以防止爲了創建成員而不斷地編輯行。

你對此有何看法?

到目前爲止,這在我看來似乎是一個好方法。花了很多心思去到這裏。我也相信它可能會隨着時間的推移而得到改進,並且能夠存儲每個成員的id數組而不是所有的成員。仍然試圖解決這個問題!