我需要将大约1,000,000条记录导入数据存储区。更重要的是,我想将其中一些记录合并为一个记录。到目前为止我尝试过的所有内容都需要永久保存,并且如果后端终止任务中途将其重新启动到另一台计算机上,则无法恢复。
我的第一次尝试是在每次插入之前查询数据存储区以将数据添加到现有匹配记录中,否则插入新记录。
Crops local = // read from CSV
for (...)
{
Crops db = ObjectifyService.ofy().load().type(Crops.class).
id(local.country + "_" + local.cropType + "_" +
new Integer(local.year).toString()).now();
if (db == null)
{
db = local;
crops.put(composite, db);
}
else
{
// add additional data to db
}
ObjectifyService.ofy().save().entity(db).now();
}
预计完成时间为13小时。
所以我尝试在本地聚合数据
Crops local = // read from CSV
HashMap<String, Crops> crops = ...
for (...)
{
String composite = local.country + "_" + local.cropType + "_" +
new Integer(local.year).toString();
Crops db = crops.get(composite);
if (db == null)
{
db = local;
crops.put(composite, db);
}
else
{
// add additional data to db
}
}
ObjectifyService.ofy().save().entities(crops.values()).now();
由于堆太大,导致程序终止。
我开始工作的一个变体是将聚合数据拆分为1000条记录的块,用于存储它们。
Iterator<Crops> sit = crops.values().iterator();
List<Crops> list = new ArrayList<Crops>(1000);
i = 0;
while (sit.hasNext())
{
list.add(sit.next());
i++;
if (i >= 1000)
{
ObjectifyService.ofy().save().entities(list).now();
list.clear();
i = 0;
}
}
ObjectifyService.ofy().save().entities(list).now();
但预计完成此课程的时间为80小时。
我想要尝试的下一件事是并行地插入这些1000块而不是顺序插入。
但是在我浪费了更多时间之前,我想问一下我是否走在正确的道路上,或者我错了。也许不可能在13个小时之内获得这样的导入?
将大型数据集导入数据存储区的最快方法是什么?
答案 0 :(得分:3)
看看MapReduce - 它是专为大型作业而设计的,可以分成较小的块。
无需检查实体是否已存在,除非此实体中的某些数据在您覆盖时会丢失。如果可以安全地覆盖它,只需插入您的实体即可。这应该会减少一半或更多的时间。
批处理数据库调用将大大加快速度。
我不知道local.year的类型,但如果是int
,您可以这样做:
String composite = local.country + "_" + local.cropType + "_" + local.year;