Python 如何将数据导入/同步到App Engine数据存储区,而无需过度读取数据存储区或超时
我正在编写一个应用程序,它使用远程API提供相当静态的数据(但仍然可以一天更新几次)。问题是API非常慢,我更愿意将数据导入到我自己的数据存储中,这样我就可以在我的终端上查询数据 问题是,结果包含约700条记录,需要每5小时左右同步一次。这包括添加新记录、更新旧记录和删除过时记录 我有一个简单的解决方案可以工作——但速度很慢,在超时之前(大约500条记录之后)使用30000个数据存储读取操作 最糟糕的是,这700条记录只针对一个客户机,而我只是做了一个测试。事实上,我想为数百或数千个记录数量相似的客户做同样的事情。。。你可以看到这是如何不扩大的 以下是我的实体类定义:Python 如何将数据导入/同步到App Engine数据存储区,而无需过度读取数据存储区或超时,python,google-app-engine,optimization,google-cloud-datastore,app-engine-ndb,Python,Google App Engine,Optimization,Google Cloud Datastore,App Engine Ndb,我正在编写一个应用程序,它使用远程API提供相当静态的数据(但仍然可以一天更新几次)。问题是API非常慢,我更愿意将数据导入到我自己的数据存储中,这样我就可以在我的终端上查询数据 问题是,结果包含约700条记录,需要每5小时左右同步一次。这包括添加新记录、更新旧记录和删除过时记录 我有一个简单的解决方案可以工作——但速度很慢,在超时之前(大约500条记录之后)使用30000个数据存储读取操作 最糟糕的是,这700条记录只针对一个客户机,而我只是做了一个测试。事实上,我想为数百或数千个记录数量相似
class Group(ndb.Model):
groupid = ndb.StringProperty(required=True)
name = ndb.StringProperty(required=True)
date_created = ndb.DateTimeProperty(required=True, auto_now_add=True)
last_updated = ndb.DateTimeProperty(required=True, auto_now=True)
以下是我的同步代码(Python):
currentTime=datetime.now()
groups=get_list_of_groups_from_api(clientid)#[{'groupname':'groupname','id':'12341235'},]
对于组中的组:
groupid=组[“id”]
groupObj=Group.get_或_insert(groupid,groupid=Group[“id”],name=Group[“name”])
groupObj.put()
staleGroups=Group.query(Group.last\u更新
我无法告诉您为什么要进行30000次读取操作
您应该首先运行appstats并分析此代码,以查看在何处执行数据存储操作
尽管如此,我可以看到您的代码中存在一些真正的低效之处
例如,您的delete-stale-groups代码效率极低
您应该先执行一个只包含密钥的查询,然后执行批量删除。
您所做的非常慢,循环中的每个delete()都有很多延迟
另外,get\u或\u insert使用一个事务(同样,如果组不存在,put已经完成,然后您执行第二个put()),如果您不需要事务,您会发现运行速度会更快。您没有存储任何附加数据这一事实意味着您可以盲写组(因此初始get/read),除非您想保留date\u created
其他加快速度的方法是对键列表执行批处理get/put。
然后对所有不存在的实体执行批处理put()
同样,这比迭代每个键要快得多
此外,您应该使用TaskQueue来运行这组代码,然后您将有一个10分钟的处理窗口
之后,可以通过将流程拆分为两个任务来实现进一步的扩展。第一个创建/更新组实体。完成后,启动删除过时组的任务—将datetime作为参数传递给下一个任务
如果您拥有的实体比这个简单模型中可以处理的还要多,那么请开始查看MapReduce
但对于初学者来说,只需将精力集中在提高当前运行的工作效率上。您能否详细说明一下,为什么每个客户机需要大约30000次阅读?当它只有大约700个实体需要处理时,我不知道为什么它使用30000个读取操作。。这是我问题的一部分。我更希望它尽可能少。我不是故意做30000次读取操作——这是我的实现的结果:/你能提供来自\u api()代码的\u组的get\u list\u吗?我怀疑您想修改它以返回较少的组…它所做的只是返回一个列表中约700个组项的列表(看起来像我在该行末尾的注释)。该函数对数据存储没有任何作用——只是对json端点的简单web请求。该函数只需5秒钟即可返回。。因此,在超时之前剩下的55秒完全是由于函数调用下面的代码中的内容。你说的远程api是什么意思?针对远程api运行的代码`/\u ah/remote\u api'可以运行数天,因此不会超时。
currentTime = datetime.now()
groups = get_list_of_groups_from_api(clientid) #[{'groupname':'Group Name','id':'12341235'}, ...]
for group in groups:
groupid = group["id"]
groupObj = Group.get_or_insert(groupid, groupid=group["id"], name=group["name"])
groupObj.put()
staleGroups = Group.query(Group.last_updated < currentTime)
for staleGroup in staleGroups:
staleGroup.delete()