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

Java Firebase数据库:在Android应用程序上查询大量数据时出现内存不足异常,java,android,firebase,firebase-realtime-database,Java,Android,Firebase,Firebase Realtime Database,我正在为我的Android应用程序使用Firebase数据库。我需要一个唯一的5位数的代码,应该是有效的3天。为了解决这个问题,我在Firebase数据库中插入了所有可能的5位代码,其中每个条目最初的状态为1。所以结构看起来像这样: codes: { 'abcde': {status:1}, 'zhghs': {status:1} ..... } 这个code对象有近500万个条目。我在想,一旦代码被使用,我会将状态设置为2 我用这个从Firebase获取代码: db.getRef

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

codes: {
  'abcde': {status:1},
  'zhghs': {status:1}
  .....
}
这个
code
对象有近500万个条目。我在想,一旦代码被使用,我会将状态设置为
2

我用这个从Firebase获取代码:

db.getReference("codes")
                .orderByChild("status")
                .limitToFirst(1)
                .addListenerForSingleValueEvent { ..... }
我只需要一个状态为
1
的代码。上面的代码导致了
OutOfMemoryException
,因此我认为它正在尝试加载设备上的所有数据。由于
limitToFirst(1)
约束,它不应该只在设备端加载一个元素吗

另外,我在Firebase FireStore试过了。目前,它不允许在每天不超过20K的限制下导入大量JSON数据

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

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

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

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

db.getReference("codes")
            .orderByChild("status")
            .equalsTo(1)
            .limitToFirst(1)
            .addListenerForSingleValueEvent { ..... }
即使有了这个限制,您也应该减少加载到内存中的数据量,因为您似乎将太多的数据强制加载到内存中。或者,您可以通过在Manifest.xml文件中设置
android:largeHeap=“true”
来设置较大的堆大小。通常这种错误会消失

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

正如@DougStevenson所说,这并不是解决OOM错误的推荐方法,但正如我在@FrankvanPuffelen的回答中所看到的,解决问题的关键是添加
“.indexOn”:“status”
,这一点最初是缺失的

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

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

db.getReference("codes")
            .orderByChild("status")
            .equalsTo(1)
            .limitToFirst(1)
            .addListenerForSingleValueEvent { ..... }
即使有了这个限制,您也应该减少加载到内存中的数据量,因为您似乎将太多的数据强制加载到内存中。或者,您可以通过在Manifest.xml文件中设置
android:largeHeap=“true”
来设置较大的堆大小。通常这种错误会消失

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


正如@DougStevenson所说,这并不是解决OOM错误的推荐方法,但正如我在@FrankvanPuffelen的回答中所看到的,解决问题的关键是添加
“.indexOn:“status”
,它最初是缺失的。

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

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

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

另请参见。

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

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

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

另请参见。

请编辑您的问题,将您的描述限制为单个问题。一切都很合理,直到你在最后列出了一堆不适合堆栈溢出的其他问题。@DougStevenson删除了它们。所以,可以肯定的是,如果你在应用程序中除了这个查询之外什么都不做,你也有同样的问题吗?@DougStevenson我的应用程序在我点击这个查询之前完全加载。确切的错误是Firebase数据库遇到OutOfMemoryError。您可能需要减少同步到客户端的数据量。java.lang.OutOfMemoryError:无法分配28701016字节分配,16777216个可用字节和18MB,直到OOM问题不是你的应用程序完全加载。(可能加载太多,谁知道呢?)。一切都很合理,直到你在最后列出了一堆不适合堆栈溢出的其他问题。@DougStevenson删除了它们。所以,可以肯定的是,如果你在应用程序中除了这个查询之外什么都不做,你也有同样的问题吗?@DougStevenson我的应用程序在我点击这个查询之前完全加载。确切的错误是Firebase数据库遇到OutOfMemoryError。您可能需要减少同步到客户端的数据量。java.lang.OutOfMemoryError:无法分配28701016字节分配,16777216个可用字节和18MB,直到OOM问题不是你的应用程序完全加载。(可能加载太多,谁知道呢?)问题在于,如果没有应用程序其余部分的上下文,查询实际上占用了太多内存。最初,所有代码的状态都为1,因此添加equalsTo(1)不会减少数据集。使用android:largeHeap=“true”对我来说不是一个正确的选择,因为我最终会转换到6位代码,那里的数据会多得多,我不想为一个代码在RAM中加载数百MB的数据。使用largeHeap并不是解决OOM错误的真正推荐方法,由于设备之间仍然存在巨大的内存差异,Android绝对没有义务为您提供超出其选择的内存。正确的解决方案是使用更少的内存。最初,所有代码的状态都为1,因此将等式添加到(1)不会减少数据