我正在编写一个使用远程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()
答案 0 :(得分:1)
我无法告诉你为什么要进行30,000次读取操作。
您应首先运行appstats并分析此代码,以查看正在执行数据存储区操作的位置。
话虽如此,我可以看到代码中存在一些真正的低效率。
例如,删除过时的组代码非常低效。
您应该执行keys_only查询,然后执行批量删除操作。 你正在做的事情非常缓慢,循环中的每个delete()都有很多延迟。
get_or_insert也使用了一个交易(如果该组没有存在已经完成的put,然后你做了第二次put()),如果你不需要交易,你会发现事情会运行得更快。您没有存储任何其他数据这一事实意味着您可以盲目地编写组(首先获取/读取),除非您想保留date_created
。
其他提高速度的方法是批量获取/放入键列表。 然后对于所有不存在的实体,执行批处理put()
同样,这比迭代每个键要快得多。
此外,你应该使用TaskQueue来运行这组代码,然后你有一个10分钟的处理窗口。
之后,可以通过将流程分成两个任务来实现进一步的扩展。第一个创建/更新组实体。完成后,您将启动删除过时组的任务 - 将日期时间作为参数传递给下一个任务。
如果你有更多的实体可以在这个简单的模型中处理,那么就开始查看MapReduce。
但对于初学者来说,只需专注于使你目前正在运作的工作更有效率。