如何在没有过多数据存储区读取或超时的情况下将数据导入/同步到App Engine数据存储区

时间:2013-11-29 18:02:11

标签: python google-app-engine optimization google-cloud-datastore app-engine-ndb

我正在编写一个使用远程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()

1 个答案:

答案 0 :(得分:1)

我无法告诉你为什么要进行30,000次读取操作。

您应首先运行appstats并分析此代码,以查看正在执行数据存储区操作的位置。

话虽如此,我可以看到代码中存在一些真正的低效率。

例如,删除过时的组代码非常低效。

您应该执行keys_only查询,然后执行批量删除操作。 你正在做的事情非常缓慢,循环中的每个delete()都有很多延迟。

get_or_insert也使用了一个交易(如果该组没有存在已经完成的put,然后你做了第二次put()),如果你不需要交易,你会发现事情会运行得更快。您没有存储任何其他数据这一事实意味着您可以盲目地编写组(首先获取/读取),除非您想保留date_created

其他提高速度的方法是批量获取/放入键列表。 然后对于所有不存在的实体,执行批处理put()

同样,这比迭代每个键要快得多。

此外,你应该使用TaskQueue来运行这组代码,然后你有一个10分钟的处理窗口。

之后,可以通过将流程分成两个任务来实现进一步的扩展。第一个创建/更新组实体。完成后,您将启动删除过时组的任务 - 将日期时间作为参数传递给下一个任务。

如果你有更多的实体可以在这个简单的模型中处理,那么就开始查看MapReduce。

但对于初学者来说,只需专注于使你目前正在运作的工作更有效率。