2009-10-07 43 views
7

我有一個應用程序利用圖(樹狀)自定義結構。這些結構不是真正的樹木,但幾乎所有東西都連接在一起。數據量也很大(可能存在數百萬個節點)。樹節點可以在類型上有所不同,以使其更有趣(繼承)。我不想改變數據結構以適應持久性存儲。持久圖數據(Java)

我想堅持這個數據,沒有太多額外的工作。我採用了一些方法來解決這個問題,但找不到符合我需要的任何東西。可能的選擇:序列化,帶有ORM(Hibernate?)的數據庫,JCR(JackRabbit?),還有其他什麼?因爲它是基於GUI的「實時」應用程序(無需批處理),並且可能有數百萬個圖形節點應該在內存和持久數據存儲之間讀取和寫入。

有沒有人有關於存儲這些類型的數據的經驗或想法?

+0

我懷疑它太籠統了,不能給出一個好的答案 - 你能列出樹結構的一些用例嗎?即如何使用它,存儲什麼(如果可能的話)。對於性能,您可能想要說明典型訪問時間需要以毫秒或其他單位的速度快多少,因爲只是說性能和「實時」非常模糊。 – Chii 2009-10-07 12:06:44

+0

當「一切都連接在一起」,它不是一棵樹,它是一張圖:http://en.wikipedia.org/wiki/Graph_%28data_structure%29也許你應該改寫標題? – nawroth 2009-10-07 13:36:23

+0

當前高性能圖形數據庫的好集合:http://java.dzone.com/news/most-trendy-graph-databases – AMilassin 2010-05-10 07:00:46

回答

5

隨着數據使用的圖形數據結構(基本上是:節點和邊緣/關係),圖形數據庫會一個非常好的比賽。有關鏈接,請參閱我在The Next-gen Databases上的回答。我是Neo4j開放源代碼圖形數據庫項目的一部分,請參閱this thread對其進行一些討論。在像您這樣的情況下使用Neo4j的一個巨大優勢是,可以輕鬆跟蹤持續/激活對象或激活深度等。您可能不需要更改應用程序中的數據結構,但當然需要一些額外的代碼。 Design guide給出了您的代碼如何與數據庫進行交互的一個示例。

2

由於您指出存在大量數據,因此您可能需要一種機制,可以根據需要輕鬆提供數據。序列化可能不是很容易處理大量的數據。爲了將其分解成可管理的部分,您需要在磁盤上使用單獨的文件或將其存儲在別處。 JCR(JackRabbit)更多的是一個內容管理系統。這些適用於'文檔'類型的對象。這聽起來像你想存儲的樹的個別部分可能很小,但它們可以很大。這不是CMS的想法。

你提到的另一個選項ORM可能是你最好的選擇。 JPA(Java持久性API)非常適合在Java中進行ORM。您可以寫入JPA規範並使用Hibernate,Eclipselink或月供應商的任何其他風格。這些將與你想要的任何數據庫一起工作。 http://java.sun.com/javaee/5/docs/api/index.html?javax/persistence/package-summary.html

JPA的另一個好處是你可以使用懶惰的FetchType加載樹的依賴關係。這樣,你的應用程序只需要加載它正在處理的當前片段。由於其他需要,JPA層可以根據需要從數據庫中檢索它們。

1

一個ORM,例如使用JPA api(Hibernate,EclipseLink,...)可能會使其非常快速地實現持久性。與普通JDBC相比,整個樹持久性的原始性能往往難以實現。所以如果你唯一的表現標準是一次性堅持整棵樹,那可能不是最好的選擇。另一方面,如果您還需要加載樹,同步樹的更改,那麼JPA提供的內置特性(經過一些調整後)比許多手動實現具有更好的性能。

在java中的序列化往往是相當緩慢,併產生大量的數據。如果您需要同步樹更改,則在應用中更改類時序列化也非常脆弱,並且完全沒有用處。

在與序列化相同的類別中,您可以使用XML序列化並將其保存在某個XML數據庫(Oracle XDB)中。然而,這些設計更多地是爲了存儲/查詢的靈活性而非原始速度。

如果時間不是問題,最好的方法是始終讓一個合格的DBA參與並設計一個最佳數據模型並相應地重構樹。

2

我幾乎有確切的問題,並使用休眠。我們在項目後期遇到了很多問題,因爲即使使用懶惰提取類型,視圖基本上也會將整個圖形強制到內存中。這些工具在早期階段很好,因爲我們可以快速獲得一個DB層,這給了我們一些東西(huzzah敏捷)。只有當我們要提高性能時,我們才意識到我們需要編寫更智能的持久層。

是否可以對數據進行一些預處理?如果問題類似,則嘗試將數據轉換爲比原始域更接近視圖的中間表單並將其存儲在數據庫中也有很大的價值。您始終可以使用懶惰獲取類型鏈接回原始來源。

基本上,我們使用了4層系統:域DB,視圖模型-DB雜交體(預處理層),視圖模型,視圖

此預處理步驟(特別是與實時UI)的優點,是您可以將數據分頁到ViewModel中並很好地呈現它。在實時應用程序中的很多性能都是微不足道的,只需保持響應並在等待時向他們展示一些不錯的內容。在我們的例子中,我們可以顯示正在分頁的數據的3d框區域,鏈接到加載數據的數據也可以顯示一個可視指示器。 ViewModel-DB混合體也可以做很好的事情,比如適合我們域數據的LRU隊列。儘管最大的優勢是消除了直接鏈接。節點有類似於鏈接數據的URL。渲染時,我們可以渲染鏈接,或者渲染出現有鏈接,我們現在只是分頁。

數據庫級別的持久性是JPA(Hibernate)的啓動,但最終它爲我們的繼承結構生成的表格非常糟糕,難以維護。最後,我們想要比JPA允許的(或者至少容易允許的)更多地控制表。這是一個艱難的決定,因爲JPA確實使很多DB層變得容易。由於JPA保持了很好的東西和POJO,所以它不需要使用我們的數據類型。所以這很好。

我希望有一些東西你可以拉出來這個蜿蜒的答案,祝你好運:)

1

考慮存儲在數據庫中的節點,一個合適的模式可能是:

t1(node_id,child_id) 
t2(node_id,data1,data2,..,datan) 

然後使用JDBC訪問/修改數據。如果您使用適當的索引,它將表現得相當好,可以擴展大約1億條記錄。 我的直覺是避免泛型對象序列化,因爲如果性能非常重要,因爲用這些解決方案失去了對代碼性能特徵的一些控制。

如果您需要更好的性能,可以使用memcached圖層。

0

我相信你的問題的解決方案是使用Terracotta作爲你的永久存儲機制。我鼓勵你閱讀this excellent article這樣做。

它解決了您的兩個主要問題:性能透明度。它很容易擴展到大型圖形,同時保持高性能,因爲其高效的同步機制只能通過網絡發送實例差異。它還可以透明地保存圖形,因爲它可以在VM級別上工作,從而免除了其他答案(ORM或OCM)中提到的替代方案所面臨的阻抗不匹配問題。

要清楚,兵馬俑是不是爲每個案件的持久性解決方案。當您需要跨計算機重啓時可用的數據並且您需要快速使用它時,它的使用效果最佳。當您需要「歸檔」數據時,這不是一個好的解決方案,例如在運行系統停止使用數據後很長時間就要求訪問該數據。考慮進入網上商店的訂單。您可能想要在完成這些訂單後多年存儲這些訂單。在這些情況下,您可以查看混合方法,將需要存檔的選擇數據從Terracotta集羣中取出並使用傳統的RDBMS進行存儲。

要得到更完整的評論&缺點,請務必閱讀this StackOverflow post,其中涵蓋了更多的細節做出選擇。