2010-06-24 21 views
1

我有一個用PHP編寫的網站。它目前使用MySQL來滿足所有的數據庫需求(我可以使用其他數據庫技術)。我應該如何存儲非樹分層數據(即任何通用圖)?

系統的內容是相互關聯的。這些關係可以表示爲一個圖,其中頂點是內容片段,邊是關係。我需要能夠遍歷該圖。我特別需要能夠:

  • 得到孩子數在給定的深度(例如許多grandchildrean如何確實有一個項目)
  • 獲取累積孩子數在給定的深度(例如有多少孩子和孫子們做的項目有)
  • 獲取最大深度爲給定根(例如,什麼是該項目的最長路徑)
  • 在給定的深度把孩子們(如誰是這個項目的孫子)
  • 讓父母在特定的深度(例如,誰是這個項目的祖父母)
  • 查看哪些狀態(如「隱藏」或「鎖定」)已從父母繼承。

因爲它是一個動態的系統上的圖形,而不是一棵樹或傳統的等級,也有我認爲排除通常的基於SQL的技巧(例如鄰接表和路徑枚舉)的一些複雜性。

主余光中:

  • 內容可以有不止一個孩子。

  • 內容可以有多個父母。

  • 對於每個用戶,項目的關係圖可能看起來不同。例如,某些內容可能對一個人隱藏,而對另一個人隱藏。

  • 項目可以在圖樹上多次出現,並且可以以不同的路徑長度出現(例如,項目50可以是直接孩子,同時也是第三代孩子)。

  • 圖可以包含數十萬個項目。

一些額外的余光中:

  • 不同類型的內容可以與(如,民意調查可能與一個論壇帖子,或用戶可能與社區)

  • 有幾種不同類型的關係(如,父/子關係,產權關係,同伴關係)

  • 根據關係的類型,許可和限制可能會或可能不會從父母傳遞給孩子(例如,如果父母是隱藏的,孩子會被隱藏好,但如果對等項目被隱藏的狀態不是一起傳送)

我天真(慢)「解決方案」

目前我正在採用SQL的天真方法。我有這些列一個「關係」表:

item1ID (int) 
item1TypeID (int) 
item2ID (int) 
item2TypeID (int) 
relationshipTypeID (int) 

在PHP,我動態生成的查詢充滿內心的聯接來查找最大深度,然後一旦被想通了,我生成一個查詢它遍歷層次結構並檢索我需要的任何信息。這已經太慢了,即使有適當的索引。

我的第二個簡單的方法是將存儲過程的遍歷和深度查找。我不知道這是否會帶來顯着的速度提升。我也在考慮採用某種緩存機制,這樣我就可以避免像往常一樣查找最大深度,但這似乎只是避免了真正的問題。

我的問題

必須有一個更好的辦法。它是什麼?我知道StackOverflow已經有很多關於SQL中分層信息問題的問題和答案,但這不是很層次 - 它是一個完整的圖表。

由於我有強大的模型,我可以混合使用另一種數據庫技術來處理事情的關係,而不會破壞現有的代碼庫。我一直在研究NoSQL解決方案,但我幾乎不知道它們。我也聽說過「Graph Databases」(如Neo4J),它基於我所看到的名稱和幻燈片,聽起來就像我需要的。但是,我不知道哪些實際上足夠強大,可以堅持到底,哪些可以很好地利用PHP。

幫助我StackOverflow,你是我唯一的希望。

回答

1

從您的描述來看,Neo4j確實應該與您遇到的問題非常匹配。例如,關係類型支持應該在這裏證明有用。有一個active community,這增加了graphdb將存活到未來的機會。它也已經投入生產了很長一段時間。

PHP side of Neo4j到目前爲止並不是那麼光彩,但我認爲REST API開放了一些有趣的場景。有一個PHP REST client(快速介紹here)正在開發。然後有一個experiment與PHP/Java橋樑(我沒有嘗試過自己)。

請注意,您的一些要求只是非常棘手的問題,使用任何技術都無法輕鬆解決。例如,根據圖的佈局,找到最大深度可能是非常昂貴的操作。在某些情況下,它可以很好地解決插入問題,並在每個節點上存儲「孩子數量」。

關於RDBMS,我在基於PHP/MySQL的系統中遇到過類似的問題。使用存儲過程有助於構建項目,但性能實際上變得更糟(這是當時存儲過程是MySQL中的一項新功能)。根據我的經驗,PostgreSQL在複雜的查詢中執行得更好,但編寫真正的圖形查詢並不是真的可能(請閱讀herehere爲什麼這麼做!)

聲明:我是Neo4j團隊的成員

相關問題