0

我有一个 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

4

2 回答 2

2

您有来自 Java 的“打开的文件过多”错误。尝试分批添加文档,然后在每批(例如)1000 个文档之后提交和优化。存在其他解决方案,但与搜索后端相关,而不是您的 Python 脚本。

于 2013-01-14T08:37:41.280 回答
2

filedir在第 169 行重新分配,而没有关闭您在第 116 行所做的。我认为这是一个错误,因为您不需要创建新的,您可以重用旧的。另外,然后你会在每个循环左右创建它,它只会泄漏句柄,因为它们永远不会关闭。

如果有其他一些方法,您将在filedir不关闭它的情况下创建一个新方法,即第 106createEmptyIndex行和第 97 行deleteFromIndex

还有一个不太明显,在retrieveUniqID. 您正在创建,但仅在第 87 行的条件为真searcher时才关闭它。if cont == content:在没有匹配的情况下,并且您return None在第 91 行,您永远不会关闭该搜索器。在这种情况下,由于您将一个字符串传递给IndexSearcher构造函数,因此它在内部创建了一个Directory您在某些情况下不会关闭的。如果愿意,您可以使用 try/finally 块来确保始终关闭它。

上述所有调用都是从 in 的主循环中进行的incrementalIndexing,因此泄漏的句柄数量迅速增加。

此外,需要考虑的一点是:所有这些类、IndexSearcherIndexReaderIndexWriter都是Directory线程安全的,并且每次创建新类的成本都很高。重新设计可能会更好,以最大程度地减少打开和关闭它们所需的时间。它实际上可能只是您的代码,因为您可以传递已经创建的实例,这将清除不同方法中的大量初始化混乱。

由于您似乎还希望能够立即访问已编入索引的文档,IndexReader因此我会考虑通过该方法获取您的(以及您的 IndexSearcher)IndexWriter.GetReader(),或者通过刷新阅读器,如下所示reader = reader.Refresh()

于 2013-01-14T09:02:03.040 回答