0

我在这里问了一个问题。简单来说,我的算法需要一个四维数组。大小可达32G。所以我打算将它存储在 MongoDB 中。我已经以我的方式实现了它。由于我之前没用过 MongoDB,所以我的实现太慢了,那么我应该如何在 MongoDB 中存储这个四维数组呢?

一些统计数据:

更新整个阵列需要几个小时(我猜是十多个,因为我没有等待),因为我的阵列大小约为 12*7000*100*500,而我的服务器是 Windows Server 2008 R2 Standard 和 16.0GB 内存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”},“键”:“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);
    }
}
4

2 回答 2

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 )

    你从右到左,增加你的基础的力量,并将它与恰好在那个位置的任何值相乘,最后得到它们的总和。

    索引这个字段,我们应该期待更好的性能。

于 2013-07-13T14:14:28.727 回答
0

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

如果 Mongo DB 的性能对您来说足够快,我会感到非常惊讶。如果更新需要十个小时,那么扫描一次也可能需要十个小时。如果您有 SSD,内存映射文件可能需要大约三分钟。如果数据都在内存中,例如你有 48 GB(你需要 32+ GB 的空闲空间而不是总数),这将下降到几秒钟。

您无法克服硬件的限制。;)

于 2013-07-13T14:31:08.500 回答