对于 google 数据存储中的 100k+ 个实体,ndb.query().count() 将在截止日期前取消,即使有索引。我尝试过使用produce_cursors 选项,但只有iter() 或fetch_page() 会返回游标,而count() 不会。
如何计算大型实体?
对于 google 数据存储中的 100k+ 个实体,ndb.query().count() 将在截止日期前取消,即使有索引。我尝试过使用produce_cursors 选项,但只有iter() 或fetch_page() 会返回游标,而count() 不会。
如何计算大型实体?
要做一些昂贵的事情,你应该看看Task Queue Python API。Google App Engine 基于 Task Queue API,提供了延迟库,我们可以使用它来简化运行后台任务的整个过程。
以下是如何在应用程序中使用延迟库的示例:
import logging
def count_large_query(query):
total = query.count()
logging.info('Total entities: %d' % total)
然后您可以在您的应用程序中调用上述函数,例如:
from google.appengine.ext import deferred
# Somewhere in your request:
deferred.defer(count_large_query, ndb.query())
虽然我仍然不确定是否count()
要使用如此大的数据存储返回任何结果,但您可以改用这个count_large_query()
函数,它使用游标(未经测试):
LIMIT = 1024
def count_large_query(query):
cursor = None
more = True
total = 0
while more:
ndbs, cursor, more = query.fetch_page(LIMIT, start_cursor=cursor, keys_only=True)
total += len(ndbs)
logging.info('Total entitites: %d' % total)
要在本地尝试上述设置LIMIT
为 4 并检查您的控制台中是否可以看到该Total entitites: ##
行。
正如 Guido 在评论中提到的那样,这也不会扩展:
这仍然无法扩展(尽管它可能会推迟问题)。一个任务有 10 分钟而不是 1 分钟,所以也许你可以算出 10 倍的实体。但它相当昂贵!如果您想正确解决这个问题,请搜索分片计数器(不幸的是,这是很多工作)。
因此,您可能想了解编写可扩展应用程序的最佳实践 ,尤其是分片计数器。
这确实是一个令人沮丧的问题。我最近一直在这方面做一些工作,以获得一些一般的计数统计信息——基本上,满足某些查询的实体数量。count()
是一个好主意,但它受到数据存储 RPC 超时的阻碍。
如果count()
以某种方式支持游标,那就太好了,这样您就可以在结果集上游标并简单地将结果整数相加,而不是返回一个大的键列表而只是把它们扔掉。使用光标,您可以使用“传递接力棒”延迟方法继续跨越所有 1 分钟/10 分钟边界。使用count()
(相对于fetch(keys_only=True)
),您可以大大减少浪费,并有望提高 RPC 调用的速度,例如,使用该方法计数到 1,000,000 需要花费惊人的时间fetch(keys_only=True)
——这在后端是一个昂贵的提议。
如果您只需要/想要定期计数统计信息(例如,按国家/地区划分的系统中我所有帐户的每日计数),则分片计数器的开销很大。
最好使用谷歌应用引擎后端。后端不受用户请求的 60 秒期限和任务的 10 分钟期限的限制,并且可以无限期运行。请在此处查看文档:https ://developers.google.com/appengine/docs/java/backends/overview