![](/img/trans.png)
[英]How can I avoid OutOfMemoryErrors when using Commons FileUpload's DiskFileItem to upload large files?
[英]How can I avoid OutOfMemoryErrors when updating documents in a Lucene index?
我正在尝试以增量方式刷新Lucene索引,该索引用于更新已更改的文档并保持其他未更改的文档不变。
为了更新更改的文档,我使用IndexWriter.deleteDocuments(Query)
删除这些文档,然后使用IndexWriter.addDocument()
添加更新的文档。
IndexWriter.deleteDocuments
中使用的Query
对象包含大约12-15个术语。 在刷新索引的过程中,有时我还需要执行完全刷新,方法是使用IndexWriter.deleteDocuments
删除所有文档,然后添加新文档。
问题是当我说删除大约100000个文档后调用IndexWriter.flush()
时,执行时间很长,并抛出OutOfMemoryError
。 如果我禁用刷新功能,索引会快速上升到说2000000 docs删除,然后抛出OutOfMemoryError
。 我试图将IndexWriter.setRAMBufferSizeMB
设置为500,以避免出现内存不足错误,但是没有运气。 索引大小为1.8 GB。
第一 。 增加RAM缓冲区不是您的解决方案。 据我了解,这是一个缓存,我宁愿说这正在加剧您的问题。 OutOfMemoryError是JVM问题,不是Lucene问题。 您可以将RAM缓冲区设置为1TB-如果您的VM没有足够的内存,则仍然存在问题。 因此,您可以做两件事:增加JVM内存或减少消耗。
第二 。 您是否已经考虑过增加堆内存设置? 永久清除的原因是系统在内存耗尽之前不久就进行了大量垃圾回收。 这是典型症状。 您可以使用jvisualvm
类的工具进行jvisualvm
。 您需要先安装GC详细信息插件,然后才能选择并监视疯狂的OutOfMemory应用程序。 如果您了解内存问题,则可以增加最大堆空间,如下所示:
java -Xmx512M MyLuceneApp(或者,但是您启动Lucene应用程序)
但是,再次,我将使用工具来首先检查您的内存消耗配置文件和垃圾回收行为。 您的目标应该是避免内存不足,因为这会导致垃圾回收将您的应用程序减慢到无性能的状态。
第三 。 现在,如果增加堆,则必须确保还具有足够的本机内存。 因为如果您不这样做(请使用Linux上的top
工具),您的系统将开始交换到磁盘,这也会疯狂影响Lucene的性能。 因为Lucene针对顺序磁盘读取进行了优化,并且如果系统开始交换,则硬盘将执行大量磁盘搜索,这比顺序读取慢2个数量级。 因此,情况将会更糟。
第四 。 如果没有足够的内存,请考虑分批删除。 在冲洗1,000或10,000个文档后,请一次又一次冲洗。 发生OutOfMemoryError的原因是,Lucene必须将所有内容保留在内存中,直到执行刷新为止。 因此,无论如何不要让太大的批处理冲洗掉,以避免将来出现问题,这可能是一个好主意。
尝试为您的IndexWriter使用较小的RamBufferedSize。
如果缓冲区已满(或文档数达到一定水平),IndexWriter将刷新刷新。 通过将缓冲区大小设置为一个较大的数字,您将隐式推迟调用flush,这可能导致内存中的文档过多。
在极少数的情况下,我想擦除Lucene索引中的所有文档,我发现关闭IndexWriter,直接删除索引文件,然后基本上开始创建新索引的效率更高。 该操作只需要很少的时间,并且可以保证将索引保持原始状态(如果有些空的话)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.