有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java GAE对象化大规模?进口

我需要将大约1000000条记录导入数据存储。更重要的是,我想把这些记录中的一些合并成一个。到目前为止,我尝试过的所有操作都会花费很长时间,如果后端中途终止任务并在另一台机器上重新启动它,那么就不适合恢复

我的第一次尝试是在每次插入之前查询数据存储,以便将数据添加到现有的匹配记录中,或者以其他方式插入新记录

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小时内完成这样的导入

tl;博士

将大型数据集导入数据存储的最快方法是什么


共 (1) 个答案

  1. # 1 楼答案

    1. 看看MapReduce——它是专门为大规模作业设计的,这些作业可以拆分成更小的块

    2. 无需检查实体是否已存在,除非此实体中的某些数据在覆盖时会丢失。如果可以安全地覆盖,只需插入实体即可。这将把你的时间减少一半或更多

    3. 批处理数据库调用将大大加快速度

    4. 我不知道是什么类型的。年份是,但如果是int,您可以简单地执行以下操作:

      String composite = local.country + "_" + local.cropType + "_" + local.year;