当前位置: 首页 > 知识库问答 >
问题:

NDB查询超过GAE软私有内存限制

云飞翮
2023-03-14

我目前有一个在Google App Engine标准环境中运行的应用程序,其中包括一个大型天气数据数据库和一个生成数据图的前端endpoint。该数据库位于Google云数据存储中,Python Flask应用程序通过NDB库访问它。

我的问题如下:当我试图为跨越一周以上的天气数据生成图表(数据每5分钟存储一次)时,我的应用程序超出了GAE的软私有内存限制并崩溃。然而,在我的每个WeatherData实体中存储的是我想要绘制的相关字段,此外还有一个非常大的json字符串,其中包含预测数据,我不需要这个绘制应用程序。因此,导致我的应用程序超出软私有内存限制的WeatherData实体部分在此应用程序中甚至不需要。

因此,我的问题如下:是否有任何方法可以只查询实体中的某些属性,例如可以对SQL样式查询中的特定列进行查询?同样,我不需要整个forecast json字符串来作图,只需要实体中存储的几个其他字段。我尝试运行的另一种方法是一次只提取几个实体,并将查询拆分为多个API调用,但结果耗时太长,页面将超时,我无法使其正常工作。

下面是我的代码,它目前是如何实现和破坏的。非常感谢您的任何意见:

wDataCsv = 'Time,' + ','.join(wData.keys())
qry = WeatherData.time_ordered_query(ndb.Key('Location', loc),start=start_date,end=end_date)
for acct in qry.fetch():
    d = [acct.time.strftime(date_string)]
    for attr in wData.keys():
        d.append(str(acct.dict_access(attr)))
        wData[attr].append([acct.time.strftime(date_string),acct.dict_access(attr)])
    wDataCsv += '\\n' + ','.join(d)

# Children Entity - log of a weather at parent location
class WeatherData(ndb.Model):
    # model for data to save
    ...
    # Function for querying data below a given ancestor between two optional
    # times
    @classmethod
    def time_ordered_query(cls, ancestor_key, start=None, end=None):
        return cls.query(cls.time>=start, cls.time<=end,ancestor=ancestor_key).order(-cls.time)

编辑:我尝试了下面答案链接中描述的迭代页面获取策略。我的代码已更新为以下内容:

wDataCsv = 'Time,' + ','.join(wData.keys())
qry = WeatherData.time_ordered_query(ndb.Key('Location', loc),start=start_date,end=end_date)
cursor = None
while True:
    gc.collect()
    fetched, next_cursor, more = qry.fetch_page(FETCHNUM, start_cursor=cursor)
    if fetched:
        for acct in fetched:
            d = [acct.time.strftime(date_string)]
            for attr in wData.keys():
                d.append(str(acct.dict_access(attr)))
                wData[attr].append([acct.time.strftime(date_string),acct.dict_access(attr)])
            wDataCsv += '\\n' + ','.join(d)
    if more and next_cursor:
        cursor = next_cursor
    else:
        break

其中FETCHNUM=500。在这种情况下,对于与以前相同长度的查询,我仍然超出了软私有内存限制,并且查询运行的时间要长得多。我怀疑问题可能在于Python的垃圾收集器没有删除重新引用的已经使用过的信息,但即使在我包含gc时也是如此。collect()我看不出有什么改进。

编辑:

按照下面的建议,我使用投影查询修复了这个问题。我没有为每个自定义查询提供单独的投影,而是每次简单地运行相同的投影:即查询实体的所有属性,不包括JSON字符串。虽然这并不理想,因为它每次仍然从数据库中提取免费信息,但由于必要索引的指数增长,为每个特定查询生成单独查询是不可伸缩的。对于这个应用程序,因为每个附加属性是可以忽略的附加内存(除了形式json字符串),它的工作原理!

共有1个答案

谭晓博
2023-03-14

您可以使用投影查询仅从每个实体获取感兴趣的属性。不过,要注意这些限制。这仍然不能无限期地扩展。

您可以将查询拆分为多个请求(更具可伸缩性),但可以使用更大的块,而不仅仅是一对(一次可以获取500个)和游标。查看如何从google数据存储中删除所有条目的示例?

您可以将您的实例类碰撞到一个具有更多内存的类(如果尚未完成)。

您可以提前从大型实体中准备中间结果(也在数据存储中),并在最后阶段使用这些中间预计算值。

最后,您可以尝试创建和存储图形的一部分,并在最后将它们缝合在一起(只有在归结到这一点时,我不确定具体将如何完成,我想这不会是一件小事)。

 类似资料:
  • 我正在获取一个GZip LXML文件,并试图将产品条目写入数据库模型。以前,我有本地内存问题,这是通过SO(问题)的帮助解决的。现在我得到了一切工作和部署它,然而在服务器上我得到以下错误: 现在我尝试了所有我知道的方法来减少内存使用,目前正在使用下面的代码。gzip文件约为7MB,而解压缩文件约为80MB。本地代码运行良好。我试着将其作为HTTP请求和Cron作业运行,但没有什么不同。现在我想知道

  • 我们有一个可怕的经验与gae围棋。当我们的应用程序是一个免费的,我们从来没有超过软私有内存限制的问题。我们抢了定额,因此决定付款。我们每天的预算定为3美元。付费服务激活后,我们可以再次使用该网站,超额配额消失了。几个小时后,我们得到了这个超软私有内存限制,除了这个,再也看不到任何东西了。我试图清除数据存储中的一些大数据,禁用内置插件,但仍然没有运气。 我在代码中做了一些测试,以确定故障来自何处。删

  • 问题内容: 我的应用程序的用户尝试使用我的应用程序将文件作为电子邮件附件发送。但是,这样做会引发以下异常,我无法解读 什么是“软私有内存限制”?有什么可能导致此异常? 问题答案: “软专用内存限制”是App Engine将停止实例接收任何更多请求,等待任何未完成的请求并终止该实例的内存限制。当您使用过多内存时,可以将其视为正常关机。 偶尔达到软限制是可以的,因为您的所有请求均已完成。但是,每次发生

  • 我的一个GAE任务队列请求超过了软内存限制(下面的日志)。我对软内存限制的理解是,它让请求完成,然后在完成后关闭实例。 然而,从日志来看,当我达到软内存限制时,执行似乎停止了。在内存限制消息之后,我没有看到更多的日志代码,我已经检查了我的状态,看起来请求没有完成。我不确定它是否重要,但此请求正在延迟库TaskQueue中执行。 因此,如果TaskQueue达到软私有内存限制,执行是继续直到请求完成

  • 我很好奇如何处理GAE中的内存限制。目前,我有这个应用程序,需要大量的CPU/内存。 我尝试在GAE上使用b8实例运行它(基本上是使用4.8GHz CPU的顶级实例) 我还尝试手动设置CPU的数量 但无论我做什么,我总是达到同样的记忆限制。。。(见下文) GET500 0 B 43 s Unknown/_ah/start在总共处理0个请求后,超过了2048 MB的软内存限制,达到3163 MB。考

  • 我遇到偶尔错误在各种各样的请求处理程序中的应用程序引擎。我明白这个错误意味着实例使用的内存超过了分配的数量,以及这是如何导致实例关闭的。 我想了解错误的可能原因,首先,我想了解应用引擎Python实例如何管理内存。我的基本假设是: 一个F2实例以256 MB开始 当它启动时,它加载我的应用程序代码-比方说30 MB 当它处理请求时,它有226 MB可用 只要该请求不超过226 MB(误差幅度),该