ndb.query.count()在大型实体上的60s查询截止日期失败

时间:2013-02-03 14:41:06

标签: python google-app-engine app-engine-ndb bigtable

对于Google数据存储区中的100k +实体,ndb.query()。count()将在截止日期前取消,即使使用索引也是如此。我已尝试使用produce_cursors选项,但只有iter()或fetch_page()将返回游标,但count()不会。

我如何计算大型实体?

3 个答案:

答案 0 :(得分:2)

要做一些昂贵的事情,你应该看看Task Queue Python API。基于Task Queue API,Google App Engine提供deferred library,我们可以使用它来简化运行后台任务的整个过程。

以下是如何在应用中使用延迟库的示例:

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倍   很多实体。但它相当昂贵!搜索分片   计数器,如果你想妥善解决这个问题(不幸的是它很多   工作)。

因此,您可能需要查看best practices for writing scalable applications,尤其是sharding counters

答案 1 :(得分:2)

这确实是一个令人沮丧的问题。我最近在这个领域做了一些工作来得到一些一般的统计数据 - 基本上,满足一些查询的实体数量。 count()是一个好主意,但它受到数据存储区RPC超时的影响。

如果count()以某种方式支持游标,那么你可以将光标放在结果集上并简单地将结果整数加起来而不是返回大的键列表来抛弃它们。使用游标,您可以使用“传递接力棒”延迟方法继续跨越所有1分钟/ 10分钟的边界。使用count()(而不是fetch(keys_only=True)),您可以大大减少浪费,并希望提高RPC调用的速度,例如,使用{{1}计算到1,000,000需要花费大量时间方法 - 对后端的一个昂贵的主张。

如果您只需要/想要定期计数统计数据(例如,系统中我所有帐户的每日计数,例如国家/地区),则分片计数器会产生大量开销。

答案 2 :(得分:1)

最好使用谷歌应用引擎后端。 后端免于用户请求的60秒截止日期和任务的10分钟截止日期,并且无限期运行。 请在此处查看文档:{​​{3}}