我有一个python脚本来简单地将unicode句子索引到lucene索引中。它在100个句子和我的1000个句子试用中都能正常工作。然而,当我需要索引200,000个句子时,我在第4514句得到合并错误,问题是什么以及如何解决?
错误:
Exception in thread "Thread-4543" org.apache.lucene.index.MergePolicy$MergeException: java.io.FileNotFoundException: /home/alvas/europarl/index/_70g.tii (Too many open files)
at org.apache.lucene.index.ConcurrentMergeScheduler$MergeThread.run(ConcurrentMergeScheduler.java:271)
Traceback (most recent call last):
Caused by: java.io.FileNotFoundException: /home/alvas/europarl/index/_70g.tii (Too many open files)
at java.io.RandomAccessFile.open(Native Method) File "indexer.py", line 183, in <module>
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:216)
at org.apache.lucene.store.FSDirectory$FSIndexOutput.<init>(FSDirectory.java:593)
at org.apache.lucene.store.FSDirectory.createOutput(FSDirectory.java:435)
at org.apache.lucene.index.TermInfosWriter.initialize(TermInfosWriter.java:91)
at org.apache.lucene.index.TermInfosWriter.<init>(TermInfosWriter.java:83)
at org.apache.lucene.index.TermInfosWriter.<init>(TermInfosWriter.java:77)
incrementalIndexing(sfile,tfile,indexDir)
at org.apache.lucene.index.SegmentMerger.mergeTerms(SegmentMerger.java:381)
at org.apache.lucene.index.SegmentMerger.merge(SegmentMerger.java:134) File "indexer.py", line 141, in incrementalIndexing
at org.apache.lucene.index.IndexWriter.mergeMiddle(IndexWriter.java:3109)
at org.apache.lucene.index.IndexWriter.merge(IndexWriter.java:2834)
at org.apache.lucene.index.ConcurrentMergeScheduler$MergeThread.run(ConcurrentMergeScheduler.java:240)
writer.optimize(); writer.close()
lucene.JavaError: java.io.IOException: background merge hit exception: _70e:c4513 _70f:c1 into _70g [optimize]
Java stacktrace:
java.io.IOException: background merge hit exception: _70e:c4513 _70f:c1 into _70g [optimize]
at org.apache.lucene.index.IndexWriter.optimize(IndexWriter.java:1749)
at org.apache.lucene.index.IndexWriter.optimize(IndexWriter.java:1689)
at org.apache.lucene.index.IndexWriter.optimize(IndexWriter.java:1669)
Caused by: java.io.FileNotFoundException: /home/alvas/europarl/index/_70g.tii (Too many open files)
at java.io.RandomAccessFile.open(Native Method)
at java.io.RandomAccessFile.<init>(RandomAccessFile.java:216)
at org.apache.lucene.store.FSDirectory$FSIndexOutput.<init>(FSDirectory.java:593)
at org.apache.lucene.store.FSDirectory.createOutput(FSDirectory.java:435)
at org.apache.lucene.index.TermInfosWriter.initialize(TermInfosWriter.java:91)
at org.apache.lucene.index.TermInfosWriter.<init>(TermInfosWriter.java:83)
at org.apache.lucene.index.TermInfosWriter.<init>(TermInfosWriter.java:77)
at org.apache.lucene.index.SegmentMerger.mergeTerms(SegmentMerger.java:381)
at org.apache.lucene.index.SegmentMerger.merge(SegmentMerger.java:134)
at org.apache.lucene.index.IndexWriter.mergeMiddle(IndexWriter.java:3109)
at org.apache.lucene.index.IndexWriter.merge(IndexWriter.java:2834)
at org.apache.lucene.index.ConcurrentMergeScheduler$MergeThread.run(ConcurrentMergeScheduler.java:240)
我的代码:http://pastebin.com/Ep133W5f
示例输入文件: http://pastebin.com/r5qE4qpt,http://pastebin.com/wxCU277x
答案 0 :(得分:2)
您有来自Java的“打开文件太多”错误。尝试批量添加文档然后提交&amp;在每批(例如)1000个文件之后进行优化。存在其他解决方案,但与搜索后端相关,而不是与Python脚本相关。
答案 1 :(得分:2)
你在第169行重新分配filedir
,没有关闭你在第116行所做的那个。我认为这是一个错误,因为你不需要创建那个新的,你可以重用旧的一。另外,你会在每个循环左右创建它,它只会泄漏句柄,因为它们永远不会被关闭。
如果使用其他一些方法,您需要创建一个新的filedir
而不关闭它,createEmptyIndex
中的第106行和deleteFromIndex
中的第97行。
在retrieveUniqID
中还有另一个不太明显的问题。您正在创建searcher
,但只有在第87行的条件if cont == content:
为真时才关闭它。在没有匹配的情况下,以及第91行的return None
,你永远不会关闭那个搜索者。在这种情况下,由于您将字符串传递给IndexSearcher
构造函数,因此它会在内部创建一个Directory
,在某些情况下您不会关闭它。如果您愿意,可以使用try / finally块确保始终关闭它。
以上所有调用都来自incrementalIndexing
中的主循环,因此泄漏句柄的数量会迅速增加。
另外,需要考虑的事项:所有这些类IndexSearcher
,IndexReader
,IndexWriter
和Directory
都是线程安全的,创建新的类是很昂贵的每一次。通过小型重新设计可能会更好,以最大限度地减少打开和关闭它们所需的时间。它实际上可能只是你的代码,因为你可以传递已经创建的实例,这将清除不同方法中的大量初始化混乱。
由于您似乎也希望能够访问您已立即编入索引的文档,因此我会考虑通过IndexReader
方法获取您的IndexWriter.GetReader()
(以及您的IndexSearcher) ,或刷新读者,如:reader = reader.Refresh()
。