Java Firebase数据库:在Android应用程序上查询大量数据时出现内存不足异常
我正在为我的Android应用程序使用Firebase数据库。我需要一个唯一的5位数的代码,应该是有效的3天。为了解决这个问题,我在Firebase数据库中插入了所有可能的5位代码,其中每个条目最初的状态为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
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)不会减少数据