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