App Engine:检查数据存储中数据更新的最佳方法,同时避免数据存储区写入

时间:2011-06-14 10:49:04

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

我的数据存储区中有大量实体(产品)来自外部数据源。我想每天检查他们的更新。

某些项目已更新,因为应用程序直接获取了这些项目。有些是新插入的,不需要更新。

对于那些尚未获取的人,我有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调用等)。

是否有更好的方法来执行此类任务并避免不必要的数据存储区写入?

1 个答案:

答案 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')