0

Unicode 文を lucene インデックスに単純にインデックス化する Python スクリプトがあります。そして、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/r5qE4qpthttp://pastebin.com/wxCU277x

4

2 に答える 2

2

Java から「開いているファイルが多すぎます」というエラーが発生します。ドキュメントをバッチで追加してから、(たとえば) 1000 ドキュメントの各バッチの後にコミットして最適化してみてください。他の解決策は存在しますが、Python スクリプトではなく、検索バックエンドに関連しています。

于 2013-01-14T08:37:41.280 に答える
2

116行目で作成したものを閉じずに、169行目で再割り当てfiledirしています。新しいものを作成する必要がないため、古いものを再利用できるので、それは間違いだと思います。さらに、ループごとに作成すると、ハンドルが閉じられないため、ハンドルがリークするだけです。

filedir他のいくつかの方法の場合、それを閉じずに新しいものを作成します。106createEmptyIndex行目と 97 行目deleteFromIndexです。

あまり目立たないもう 1 つの例が にありretrieveUniqIDます。を作成していますが、 87 行目searcherの条件が true の場合にのみ閉じます。if cont == content:一致するものがなく、return None91 行目にいる場合、そのサーチャーを閉じることはありません。この場合、コンストラクターに文字列を渡しているため、特定のケースでは閉じていない をIndexSearcher内部的に作成しています。Directory必要に応じて、try/finally ブロックを使用して、常にブロックを閉じるようにすることができます。

上記の呼び出しはすべて のメイン ループから行われるincrementalIndexingため、リークするハンドルの数が急速に増加します。

また、考慮すべき点: これらのクラス、IndexSearcherIndexReaderIndexWriterおよびDirectoryはすべてスレッドセーフであり、毎回新しいクラスを作成するのはコストがかかります。それらを開いたり閉じたりするのに必要な時間を最小限に抑えるために、小さな再設計を行ったほうがよい場合があります。すでに作成されたインスタンスを渡すことができるため、実際には単純なコードになる可能性があります。これにより、さまざまなメソッドで多くの初期化の混乱が解消されます。

インデックスを作成したドキュメントにもすぐにアクセスできるようにしたいようですので、メソッドIndexReaderを介して (したがって IndexSearcher も同様に)取得するか、次のようにリーダーを更新することを検討します。IndexWriter.GetReader()reader = reader.Refresh()

于 2013-01-14T09:02:03.040 に答える