Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Google cloud dataflow 如何使用DatastoreIO和Dataflow对实体进行批量删除_Google Cloud Dataflow - Fatal编程技术网

Google cloud dataflow 如何使用DatastoreIO和Dataflow对实体进行批量删除

Google cloud dataflow 如何使用DatastoreIO和Dataflow对实体进行批量删除,google-cloud-dataflow,Google Cloud Dataflow,我正在尝试使用Dataflow删除数百万个数据存储实体,速度非常慢(5个实体/秒)。我希望你能向我解释一下我应该遵循的模式,让它以合理的速度发展。仅仅增加更多的工人并没有帮助 数据存储管理控制台能够删除特定类型的所有实体,但它失败很多,并且需要一周或更长时间才能删除4000万个实体。Dataflow应该能够帮助我删除数百万只匹配某些查询参数的实体 我猜应该采用某种类型的批处理策略(例如,我创建了一个包含1000次删除的变异),但我并不清楚我将如何处理。DatastoreIO一次只提供一个实体供我

我正在尝试使用Dataflow删除数百万个数据存储实体,速度非常慢(5个实体/秒)。我希望你能向我解释一下我应该遵循的模式,让它以合理的速度发展。仅仅增加更多的工人并没有帮助

数据存储管理控制台能够删除特定类型的所有实体,但它失败很多,并且需要一周或更长时间才能删除4000万个实体。Dataflow应该能够帮助我删除数百万只匹配某些查询参数的实体

我猜应该采用某种类型的批处理策略(例如,我创建了一个包含1000次删除的变异),但我并不清楚我将如何处理。DatastoreIO一次只提供一个实体供我使用。如有指点,将不胜感激

下面是我目前的慢解决方案

Pipeline p = Pipeline.create(options);
DatastoreIO.Source source = DatastoreIO.source()
    .withDataset(options.getDataset())
    .withQuery(getInstrumentQuery(options))
    .withNamespace(options.getNamespace());
p.apply("ReadLeafDataFromDatastore", Read.from(source))
 .apply("DeleteRecords", ParDo.of(new DeleteInstrument(options.getDataset())));
p.run();

static class DeleteInstrument extends DoFn<Entity, Integer> {
 String dataset;
  DeleteInstrument(String dataset) {
    this.dataset = dataset;
  }
  @Override
  public void processElement(ProcessContext c) {
    DatastoreV1.Mutation.Builder mutation = DatastoreV1.Mutation.newBuilder();
    mutation.addDelete(c.element().getKey());
    final DatastoreV1.CommitRequest.Builder request = DatastoreV1.CommitRequest.newBuilder();
    request.setMutation(mutation);
    request.setMode(DatastoreV1.CommitRequest.Mode.NON_TRANSACTIONAL);
    try {
      DatastoreOptions.Builder dbo = new DatastoreOptions.Builder();
      dbo.dataset(dataset);
      dbo.credential(getCredential());
      Datastore db = DatastoreFactory.get().create(dbo.build());
      db.commit(request.build());
      c.output(1);
      count++;
      if(count%100 == 0) {
        LOG.info(count+"");
      }
    } catch (Exception e) {
      c.output(0);
      e.printStackTrace();
    }
  }
}
Pipeline p=Pipeline.create(选项);
DatastoreIO.Source Source=DatastoreIO.Source()
.withDataset(options.getDataset())
.withQuery(getInstrumentQuery(选项))
.withNamespace(options.getNamespace());
p、 apply(“ReadLeafDataFromDatastore”,Read.from(source))
.apply(“DeleteRecords”,ParDo.of(新的DeleteInstrument(options.getDataset())));
p、 run();
静态类DeleteInstrument扩展了DoFn{
字符串数据集;
DeleteInstrument(字符串数据集){
this.dataset=数据集;
}
@凌驾
公共void processElement(ProcessContext c){
DatastoreV1.Mutation.Builder Mutation=DatastoreV1.Mutation.newBuilder();
addDelete(c.element().getKey());
最终DatastoreV1.CommitRequest.Builder请求=DatastoreV1.CommitRequest.newBuilder();
请求突变(突变);
setMode(DatastoreV1.CommitRequest.Mode.NON_事务);
试一试{
DatastoreOptions.Builder dbo=新的DatastoreOptions.Builder();
数据集(dataset);
凭证(getCredential());
Datastore db=DatastoreFactory.get().create(dbo.build());
提交(request.build());
c、 产出(1);
计数++;
如果(计数%100==0){
LOG.info(计数+“”);
}
}捕获(例外e){
c、 输出(0);
e、 printStackTrace();
}
}
}

使用当前版本的DataStoreo无法直接删除实体。在下一个数据流版本中,这个版本的DatastoreIO将被弃用,取而代之的是新版本(v1beta3)。我们认为提供delete实用程序(通过示例或pttransform)是一个很好的用例,但仍在进行中

现在,您可以批量删除,而不是一次删除一个:

  public static class DeleteEntityFn extends DoFn<Entity, Void> {
    // Datastore max batch limit
    private static final int DATASTORE_BATCH_UPDATE_LIMIT = 500;
    private Datastore db;
    private List<Key> keyList = new ArrayList<>();

    @Override
    public void startBundle(Context c) throws Exception {
      // Initialize Datastore Client 
      // db = ...  
    }

    @Override
    public void processElement(ProcessContext c) throws Exception {
      keyList.add(c.element().getKey());
      if (keyList.size() >= DATASTORE_BATCH_UPDATE_LIMIT) {
        flush();
      }
    }

    @Override
    public void finishBundle(Context c) throws Exception {
      if (keyList.size() > 0) {
        flush();
      }
    }

    private void flush() throws Exception {
      // Make one delete request instead of one for each element.
      CommitRequest request =
          CommitRequest.newBuilder()
              .setMode(CommitRequest.Mode.NON_TRANSACTIONAL)
              .setMutation(Mutation.newBuilder().addAllDelete(keyList).build())
              .build();
      db.commit(request);
      keyList.clear();
    }
  }
公共静态类DeleteEntityFn扩展了DoFn{
//数据存储最大批量限制
私有静态最终int数据存储\u批量\u更新\u限制=500;
私有数据存储数据库;
private List keyList=new ArrayList();
@凌驾
public void startBundle(上下文c)引发异常{
//初始化数据存储客户端
//db=。。。
}
@凌驾
public void processElement(ProcessContext c)引发异常{
添加(c.element().getKey());
if(keyList.size()>=数据存储\u批处理\u更新\u限制){
冲洗();
}
}
@凌驾
公共void finishBundle(上下文c)引发异常{
如果(keyList.size()>0){
冲洗();
}
}
私有void flush()引发异常{
//对每个元素发出一个删除请求,而不是一个。
委托请求=
委托书.新造船商()
.setMode(CommitRequest.Mode.NON_事务性)
.setMutation(Mutation.newBuilder().addAllDelete(keyList.build())
.build();
提交(请求);
keyList.clear();
}
}

谢谢,我会尝试一下,看看效果如何。我可以通过添加更多的工作人员(--numWorkers=20)来加快删除速度吗?我不清楚Dataflow如何分配已配置的工作线程。如果待办事项是删除,那么读取键的速度就没有帮助了。我可以确认,添加更多的运行程序实际上会降低删除速度。“太多争用”错误会导致每秒实体数减少75%左右。