繁体   English   中英

更新Lucene索引中的文档时如何避免OutOfMemoryErrors?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM