2013-07-13 30 views
0

我問了一個問題here。簡單地說,我的算法需要一個四維數組。尺寸可達32G。所以我打算將它存儲在MongoDB中。我用我的方式實現了它。由於我以前從未使用過MongoDB,因此我的實現太慢了,那麼應該如何將這個四維數組存儲在MongoDB中?如何在mongoDB中存儲多維數組

一些統計:

這將需要幾個小時(十餘我想,因爲我沒有等),以更新整個數組作爲我的數組大小約12 * 7000 * 100 * 500,和我服務器是Windows Server 2008 R2 Standard,內存爲16.0GB,CPU爲2.67GHz的Intel(R)Xeon(R)CPU。我的mongoDB版本是2.4.5

解釋一下我的實現。 我的數組有四個維度,分別命名爲z,d,wt,wv

首先,我爲數組元素構造一個字符串。以數組元素p_z_d_wt_wv [1] [2] [3] [4]爲例,因爲z是1,d是2,wt是3,wv是4,我得到一個字符串「1_2_3_4」,它代表p_z_d_wt_wv [ 1] [2] [3] [4]。然後,我將p_z_d_wt_wv [1] [2] [3] [4]的值存儲在數據庫中。 使我的數據看起來象下面這樣:

{ 「_id」:{ 「$ OID」: 「51e0c6f15a66ea5c32a99773」}, 「關鍵」: 「1_2_3_4」, 「價值」:113.1232}

{「 _id」:{ 「$ OID」: 「51e0c6f15a66ea5c32a99774」}, 「關鍵」: 「1_2_3_5」, 「價值」:11.1243}

任何意見,將不勝感激!

感謝提前!

下面是我的代碼

public class MongoTest { 

    private Mongo mongo = null; 
    private DB mmplsa; 
    private DBCollection p_z_d_wt_wv; 
    private DBCollection p_z_d_wt_wv_test; 
    public void init() 
    { 
     try{ 
     mongo = new Mongo(); 
     } catch (UnknownHostException e) { 
      e.printStackTrace(); 
     } catch (MongoException e) { 
      e.printStackTrace(); 
     } 

     mmplsa = mongo.getDB("mmplsa"); 
     p_z_d_wt_wv = mmplsa.getCollection("p_z_d_wt_wv");  
    } 

    public void createIndex() 
    { 
     BasicDBObject query = new BasicDBObject("key",1); 
      p_z_d_wt_wv.ensureIndex(query,null, true); 
    } 

    public void add(String key, double value) 
    { 
     DBObject element = new BasicDBObject(); 
     element.put("key", key); 
      element.put("value", value); 
     p_z_d_wt_wv.insert(element); 
    } 

    public Double query(String key) 
    { 

     BasicDBObject specific_key = new BasicDBObject("value",1).append("_id", false); 
     DBObject obj = p_z_d_wt_wv.findOne(new BasicDBObject("key",key),specific_key);  
      return (Double)obj.get("value"); 
    } 

    public void update(boolean ifTrainset, String key, double new_value) 
    { 
     BasicDBObject query = new BasicDBObject().append("key", key); 
     BasicDBObject updated_element = new BasicDBObject(); 
     updated_element.append("$set", new BasicDBObject().append("value", new_value)); 
     p_z_d_wt_wv.update(query, updated_element); 
    } 
} 
+0

你也可以給我們一些關於它有多慢,機器規格,mongo版本的統計數據。 – bsd

+0

我已將這些統計信息添加到我的帖子中。感謝您的提醒 – ningyuwhut

回答

0

幾點建議

  • 因爲你的數據庫規模已突破(實際上是2X)的RAM的大小。也許你應該看看Sharding。當你可以將數據庫大小放在內存中時,Mongo運行良好。

  • 存儲字段作爲一個字符串不僅消耗更多的內存,字符串比較更慢。我們可以輕鬆地將此字段存儲在NumberLong(MongoDB的長數據類型)中。由於您已經知道陣列的最大尺寸是12 * 7000 * 100 * 500

    我假設最大尺寸爲任何尺寸不能超過10,000。因此,您收藏中的元素總數少於(10000 ** 4)。

    因此,如果你想在p_z_d_wt_wv 1元素[2] [3] [4] 您計算索引作爲

    (10000 ** 0 * )+(10000 ** 1 * )+(10000 ** 2 * 3 )+(10000 * 3 * )

    你去從右到左,增加你的基地的力量,與任何價值恰好是乘以那個位置,並最終拿出他們的總和。

    索引此字段,我們應該期望更好的性能。

+0

Sharding旨在保持重負載下的高分貝性能,即使您的系統具有可擴展性。數據大小通常超過RAM大小(也是數百倍),但在所有這些情況下都不需要分片。在某些情況下,即使數據大小適合您的RAM大小,也可能需要分片。爲了保持性能,你必須確保你的_indexes_size_符合RAM大小。 – Marcello

0

既然你只是一個巨大的數組,我建議你使用內存映射文件。這將使用大約32 GB的磁盤空間,並且效率更高。即使如此,隨機訪問比主內存大的數據集總是會變慢,除非你有一個快速的SDD(購買更多的內存會更便宜)

如果MongoDB的性能足夠快,您。如果更新需要十個小時,則掃描一次也可能需要十個小時。如果您有SSD,內存映射文件可能需要大約三分鐘。如果數據全部在內存中,例如你有48 GB(你需要32 GB以上的免費總數),這將會下降到秒。

您無法打敗硬件的限制。 ;)

+0

感謝您的幫助。 Java中的內存映射文件有一個大小限制,因爲該數組的大小可以達到32G – ningyuwhut

相關問題