我问了一个问题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);
}
}
答案 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以上的免费总数),这会下降到几秒钟。
您无法超越硬件的限制。 ;)