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

时间:2018-07-03 20:07:34

标签: java android firebase firebase-realtime-database

我正在为我的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)的限制,它不应该只是在设备端加载一个元素吗?

P.S。我已经尝试过Firebase FireStore。到目前为止,不允许每天导入大量JSON数据且每天的限制不超过20K。

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

  

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

2 个答案:

答案 0 :(得分:1)

  

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

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

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

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

您也可以在这篇密切相关的文章here中查看讨论。

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

答案 1 :(得分:1)

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

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

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

另请参阅documentation on indexing data