我正在编写一个使用远程API的应用程序,该API提供相当静态的数据(但仍然可以一天更新几次)。问题是API相当慢,而且我更愿意将这些数据导入到我自己的数据存储中,这样我也可以在我的一端实际查询数据。
问题是结果包含大约700条记录,需要每隔5个小时左右同步一次。这包括添加新记录、更新旧记录和删除陈旧记录。
我有一个简单的有效的解决方案--但是它非常慢,并且在超时之前(大约500条记录之后)使用30,000个数据存储读取操作。
最糟糕的是,这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':'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()发布于 2013-11-30 07:01:49
我不能告诉你为什么你得到了30,000个读操作。
您应该首先运行appstats并分析此代码,以查看执行数据存储操作的位置。
也就是说,我可以在你的代码中看到一些真正的低效。
例如,删除陈旧的组代码效率非常低。
您应该先执行keys_only查询,然后执行批删除。你正在做的事情真的很慢,循环中的每个delete()都有很大的延迟。
此外,get_or_insert还使用事务(如果组不存在,则put已经完成,然后执行第二个put()),如果不需要事务,您会发现运行速度会更快。事实上,您没有存储任何额外的数据,这意味着您可以只对组进行盲写(所以最初是get/read),除非您想保留date_created。
其他更快的方法是在键列表上进行批处理get/put。然后,对于所有不存在的实体,执行批处理put()
同样,这将比迭代每个键要快得多。
此外,您应该使用TaskQueue来运行这组代码,然后您将有一个10分钟的处理窗口。
之后,可以通过将流程拆分为两个任务来实现进一步的扩展。第一个用于创建/更新组实体。完成后,启动删除过时组的任务-将datetime作为参数传递给下一个任务。
如果您拥有的实体比这个简单模型所能处理的实体还要多,那么就开始考虑MapReduce。
但对于初学者来说,只要专注于让你目前正在运行的工作更有效率就行了。
https://stackoverflow.com/questions/20291270
复制相似问题