如何在mongoDB中存储多维数组

时间:2013-07-13 13:05:10

标签: java mongodb mongodb-java

我问了一个问题here。简单来说,我的算法需要一个四维数组。尺寸可以达到32G。所以我计划将它存储在MongoDB中。我以我的方式实现了它。因为我以前从不使用MongoDB,所以我的实现太慢了,所以我应该如何在MongoDB中存储这个四维数组呢?

一些统计数据:

由于我的阵列大小约为12 * 7000 * 100 * 500,而且我的服务器是Windows Server 2008 R2 Standard,因此需要花费数小时(我猜不到十几个,因为我没等)来更新整个阵列16.0GB ram和cpu是Intel(R)Xeon(R)CPU,2.67GHz。我的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”},“key”:“1_2_3_4”,“value”:113.1232}

     

{“_ id”:{“$ oid”:“51e0c6f15a66ea5c32a99774”},“key”:“1_2_3_5”,“value”: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);
    }
}

2 个答案:

答案 0 :(得分:0)

很少有建议

  • 由于您的数据库大小超过(实际上是2倍)RAM的大小。也许你应该看看Sharding。当您可以在内存中调整数据库大小时,Mongo运行良好。

  • 将字段存储为字符串不仅会消耗更多内存,因此字符串比较会更慢。我们可以轻松地将此字段存储在NumberLong(MongoDB的Long DataType)中。由于您已经知道阵列的最大尺寸为12 * 7000 * 100 * 500

    我认为任何维度的最大尺寸不能超过10,000。因此,集合中元素的总数小于(10000 ** 4)。

    所以,如果你想要p_z_d_wt_wv 1 [2] [3] [4]中的元素 您将索引计算为

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

    你从右到左,增加基数的力量,并将其乘以该位置的任何值,最后得到它们的总和。

    为此字段编制索引,我们应该期待更好的表现。

答案 1 :(得分:0)

由于你只有一个庞大的数组,我建议你使用一个内存映射文件。这将使用大约32 GB的磁盘空间并且效率更高。即便如此,随机访问大于主内存的数据集总是会很慢,除非你有一个快速的SDD(购买更多内存会更便宜)

如果Mongo DB能为您提供足够快的速度,我会非常惊讶。如果更新需要十个小时,那么扫描一次也可能需要十个小时。如果您有SSD,则内存映射文件可能需要大约三分钟。如果数据全部存储在内存中,例如你有48 GB(你需要32 GB以上的免费总数),这会下降到几秒钟。

您无法超越硬件的限制。 ;)