Firebase数据库:在Android应用程序上查询大量数据的内存不足异常



我正在为我的Android应用使用Firebase数据库。我需要一个唯一的 5 位数代码,有效期为 3 天。为了解决这个问题,我在Firebase数据库中插入了所有可能的5位数代码,其中每个条目最初的状态为1。所以结构看起来像这样:

codes: {
'abcde': {status:1},
'zhghs': {status:1}
.....
}

codes对象有近 500 万个条目。我想一旦使用代码,我会将状态设置为2

我正在使用它从Firebase获取代码:

db.getReference("codes")
.orderByChild("status")
.limitToFirst(1)
.addListenerForSingleValueEvent { ..... }

我只需要 1 个状态为1的代码。上面的代码导致OutOfMemoryException所以我认为它正在尝试加载设备上的所有数据。由于limitToFirst(1)约束,它不应该只在设备端加载一个元素吗?

附言我已经尝试过Firebase FireStore。到目前为止,它不允许在不超过 20K 每日限制的情况下导入大量 JSON 数据。

编辑 - 我什至设置了db.setPersistenceEnabled(false)确切的错误是:

Firebase Database 遇到 OutOfMemoryError。您可能需要 减少同步到客户端的数据量。 java.lang.OutOfMemoryError: 无法分配 28701016 字节 分配 16777216 个可用字节和 18MB,直到 OOM

听起来您可能没有在status属性上定义索引。在这种情况下,服务器无法为您进行排序/过滤,它将在客户端中完成。这意味着客户端必须读取所有数据并将其保存在内存中,从而解释了巨大的内存使用量。

解决方案非常简单:在status属性上定义一个索引。

{
"rules": {
"codes": {
".indexOn": "status"
}
}
}

另请参阅有关索引数据的文档。

我只需要 1 个状态为 1 的代码。

在这种情况下,请将查询更改为:

db.getReference("codes")
.orderByChild("status")
.equalsTo(1)
.limitToFirst(1)
.addListenerForSingleValueEvent { ..... }

即使有此约束,您也应该减少加载到内存中的数据量,因为似乎您强制将太多数据强制到内存中。或者,您可以通过在 Manifest.xml 文件中设置android:largeHeap="true"来设置较大的堆大小。通常此错误会消失。

您还可以在此处查看这篇密切相关的文章中的讨论。

正如@DougStevenson所说,并不是解决OOM错误的推荐方法,但正如我在@FrankvanPuffelen答案中看到的那样,解决问题的关键是添加最初缺少".indexOn": "status"

最新更新