【问题标题】:Deleting massive of entities from Google App Engine NDB从 Google App Engine NDB 中删除大量实体
【发布时间】:2015-08-17 06:29:07
【问题描述】:

以前的人在我们的 Google App Engine 应用程序中制造了一些问题。目前,该应用正在使用 NULL 值保存实体,但如果我们可以清理所有这些值会更好。

这里是 ndb.Modal:

class Day(ndb.Model):
    date = ndb.DateProperty(required=True, indexed=True)
    items = ndb.StringProperty(repeated=True, indexed=False)
    reason = ndb.StringProperty(name="cancelled", indexed=False)

    is_hole = ndb.ComputedProperty(lambda s: not bool(s.items or s.reason))

不知何故,我们需要删除所有Days,其中is_holetrue

大约有 4 000 000 个实体,其中应该在服务器上删除大约 2 000 000 个。

到目前为止的代码

我认为最好先用这段代码计算我们应该删除多少实体:

count = Day.query(Day.is_hole != False).count(10000)

这(限制为 10 000)大约需要 5 秒才能运行。没有限制,它会变成DeadLineException

为了删除,我试过这个代码:

ndb.delete_multi([key for key in Day.query(Day.is_hole != False).fetch(10000, keys_only=True)])

这(有限制)大约需要 30 秒。

问题

我怎样才能更快删除所有Day where is_hole != False

(我们使用的是 Python)

【问题讨论】:

  • 如果您不介意它运行更长时间,您可以通过 remote_api 和基于您已有的游标来完成。这样它就可以随心所欲地运行,只需确保每次往返都使用可以在 60 秒内完成的批量大小。

标签: google-app-engine google-cloud-datastore app-engine-ndb


【解决方案1】:

不,没有更快的删除实体的方法 - 截止日期是固定的。

但是有一些技巧。

  1. 如果您使用https://cloud.google.com/appengine/docs/python/taskqueue/,您可以延长截止日期,您可以将一些任务放入队列中,在第一个任务之后生成下一个任务(重复)。
  2. 另一个类似于任务队列的选项是在删除一些坏记录后重定向到正在删除的同一处理程序,而最后一条记录将被删除。需要浏览器打开到最后。
如果至少有一个坏记录: delete_some_records (不超过 30s) 再次生成此任务或重定向到此处理程序(下一次调用将有接下来的 30 秒)

请记住,如果没有更多好的记录,它就有退出点。它会删除所有匹配的记录,无需再次点击。

【讨论】:

    【解决方案2】:

    最好的方法是使用 MapReduce,它会在任务队列中运行,你也可以做分片来并行工作。这是python代码。如果您需要任何说明,请告诉我

    ma​​in.py

    from mapreduce import base_handler
    from mapreduce import mapreduce_pipeline
    from mapreduce import operation as op
    from mapreduce.input_readers import InputReader
    from google.appengine.api import app_identity
    
    def deleteEntity(entity):
        yield op.db.Delete(entity)
    
    class DeleteEntitiesPipeline(base_handler.PipelineBase):
        def run(self):
            bucket_name = (app_identity.get_default_gcs_bucket_name())
            yield mapreduce_pipeline.MapPipeline(
                    "job_name", 
                    "main.deleteEntity", 
                    "mapreduce.input_readers.DatastoreInputReader", 
                    params={
                        "entity_kind": 'models.Day',
                        "filters": [("is_hole", "=", True)],
                        "bucket_name": bucket_name
                    },
                    shards=5)
    
    class StartDelete(webapp2.RequestHandler):
        def get(self):
            pipeline = DeleteEntitiesPipeline()
            pipeline.start()
    
    application = webapp2.WSGIApplication([
        ('/deleteentities', StartDelete),
    ], debug=True)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多