以前的家伙在我们的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))
不知何故,我们需要删除Day
为is_hole
的所有true
。
大约有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
is_hole != False
?
(我们正在使用Python)
答案 0 :(得分:1)
不,没有更快的方法来删除实体 - 截止日期已修复。
但是有一些技巧。
if at_least_one_bad_record: delete_some_records (not longer than 30s) spawn again this task or redirect to this handler (next call will have next 30s)
请记住,如果没有更好的记录,它有退出点。它将删除所有匹配的记录而不再次单击。
答案 1 :(得分:1)
最好的方法是使用MapReduce,它将在任务队列中运行,你也可以进行分片以平行工作。这是python代码。如果您需要任何澄清,请告诉我
<强> main.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)