我的数据存储区中有大量实体(产品)来自外部数据源。我想每天检查他们的更新。
某些项目已更新,因为应用程序直接获取了这些项目。有些是新插入的,不需要更新。
对于那些尚未获取的人,我有cron作业在运行。我使用的是Python API。
目前我做了以下事情。
我有一个字段
dateupdated = db.DateTimeProperty(auto_now_add=True)
然后我可以使用
query = dbmodel.product.all()
query.filter('dateupdated <', newdate)
query.order('dateupdated')
results = query.fetch(limit=mylimit, offset=myoffset)
选择最旧的条目并安排它们进行更新。我使用具有自定义任务名称的任务队列来确保每个产品更新每天只运行一次。
问题是,我需要更新字段dateupdated,这意味着数据存储区写入,即使产品的数据没有更改,也只是为了跟踪更新过程。
这消耗了大量的资源(CPU小时数,数据存储区API调用等)。
是否有更好的方法来执行此类任务并避免不必要的数据存储区写入?
答案 0 :(得分:1)
是的,请使用cursors
通过dateupdated
排序查询,然后在处理完实体后存储光标,您可以稍后重新运行相同的查询,只获取上次查询后更新的项目。
所以,给出像
这样的课程class MyEntity(db.model):
dateupdated = db.DateTimeProperty(auto_now_add=True)
您可以将处理程序设置为像以下任务一样运行:
class ProcessNewEntities(webapp.RequestHandler):
def get(self):
"""Run via a task to process batches of 'batch_size'
recently updated entities"""
# number of eneities to process per task execution
batch_size = 100
# build the basic query
q = MyEntity.all().order("dateupdated")
# use a cursor?
cursor = self.request.get("cursor")
if cursor:
q.with_cursor(cursor)
# fetch the batch
entities = q.fetch(batch_size)
for entity in entities:
# process the entity
do_your_processing(entity)
# queue up the next task to process the next 100
# if we have no more to process then delay this task
# for a while so that it doesn't hog the application
delay = 600 if len(entities)<batch_size else 0
taskqueue.add(
url='/tasks/process_new_entities',
params={'cursor': q.cursor()},
countdown=delay)
然后你只需要触发任务执行的开始,如:
def start_processing_entities():
taskqueue.add(url='/tasks/process_new_entities')