【问题标题】:Lucene Java opening too many files. Am I using IndexWriter properly?Lucene Java 打开太多文件。我是否正确使用 IndexWriter?
【发布时间】:2011-06-19 16:24:53
【问题描述】:

我的 Lucene Java 实现占用了太多文件。我按照 Lucene Wiki 中关于打开文件过多的说明进行操作,但这只会帮助减缓问题。这是我将对象(PTicket)添加到索引的代码:

//This gets called when the bean is instantiated
public void initializeIndex() {
    analyzer = new WhitespaceAnalyzer(Version.LUCENE_32);
    config = new IndexWriterConfig(Version.LUCENE_32, analyzer);

}


public void addAllToIndex(Collection<PTicket> records) {  
    IndexWriter indexWriter = null;
    config = new IndexWriterConfig(Version.LUCENE_32, analyzer);

    try{
        indexWriter = new IndexWriter(directory, config);
        for(PTicket record : records) {
            Document doc = new Document();
            StringBuffer documentText = new StringBuffer();
            doc.add(new Field("_id", record.getIdAsString(), Field.Store.YES, Field.Index.ANALYZED));
            doc.add(new Field("_type", record.getType(), Field.Store.YES, Field.Index.ANALYZED));

            for(String key : record.getProps().keySet()) {
                List<String> vals = record.getProps().get(key);

                for(String val : vals) {
                    addToDocument(doc, key, val);
                    documentText.append(val).append(" ");
                }
            }
            addToDocument(doc, DOC_TEXT, documentText.toString());        
            indexWriter.addDocument(doc);    
        }

        indexWriter.optimize();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        cleanup(indexWriter);
    }
}

private void cleanup(IndexWriter iw) {
    if(iw == null) {
        return;
    }

    try{
        iw.close();
    } catch (IOException ioe) {
        logger.error("Error trying to close index writer");
        logger.error("{}", ioe.getClass().getName());
        logger.error("{}", ioe.getMessage());
    }
}

private void addToDocument(Document doc, String field, String value) {
    doc.add(new Field(field, value, Field.Store.YES, Field.Index.ANALYZED));
}

编辑以添加搜索代码

public Set<Object> searchIndex(AthenaSearch search) {  

    try {
        Query q = new QueryParser(Version.LUCENE_32, DOC_TEXT, analyzer).parse(query);

        //search is actually instantiated in initialization.  Lucene recommends this.
        //IndexSearcher searcher = new IndexSearcher(directory, true);
        TopDocs topDocs = searcher.search(q, numResults);
        ScoreDoc[] hits = topDocs.scoreDocs;
        for(int i=start;i<hits.length;++i) {
            int docId = hits[i].doc;
            Document d = searcher.doc(docId);
            ids.add(d.get("_id"));
        }
        return ids;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

此代码位于 Web 应用程序中。

1) 这是使用 IndexWriter 的建议方法吗(在每次添加到索引时实例化一个新的)?

2) 我听说提高 ulimit 会有所帮助,但这似乎只是一种无法解决实际问题的创可贴。

3) 问题可能出在 IndexSearcher 上吗?

【问题讨论】:

  • 只需增加服务器上文件描述符的数量

标签: java lucene


【解决方案1】:

1) 这是建议的使用方式吗 IndexWriter(实例化一个新的 每次添加到索引)?

我建议不,在包含索引的目录中有constructors,它将检查是否存在或创建新的写入器。如果你重用 indexwriter,问题 2 将得到解决。

编辑:

好吧,在 Lucene 3.2 中似乎最多但不推荐使用一个构造函数,因此可以通过使用值为 CREATE_OR_APPEND 的 Enum IndexWriterConfig.OpenMode 来实现 Indexwriter 的恢复。

另外,打开新写入器并关闭每个文档添加效率不高,我建议重用,如果你想加快索引速度,设置setRamBufferSize默认值是16MB,所以通过试错法来做

来自文档:

请注意,您可以使用以下命令打开索引 create=true 即使读者是 使用索引。老读者会 继续搜索“时间点” 他们已经打开的快照,并且不会 查看新创建的索引,直到他们 重新打开。

同样重用IndexSearcher,我看不到搜索代码,但Indexsearcher是线程安全的,也可以用作Readonly

我也建议你在 writer 上使用 MergeFactor,这不是必需的,但有助于限制倒排索引文件的创建,通过试错法来做到这一点

【讨论】:

  • IndexWriter 的所有构造函数在 Lucene 3.2 中都已被弃用,除了我正在使用的那个。我会检查 IndexSearcher
  • 有谁知道为什么 IndexWriter 的这种构造方法被弃用了
【解决方案2】:

我认为我们需要查看您的搜索代码才能确定,但​​我怀疑这是索引搜索器的问题。更具体地说,请确保您的索引阅读器在完成后正确关闭。

祝你好运,

【讨论】:

  • 我不会关闭 IndexSearcher,因为 Lucene 说没关系。来自他们的 Wiki “确保您只打开一个 IndexSearcher,并在所有正在执行搜索的线程之间共享它——这是安全的,它将最大限度地减少同时打开的文件数量。”不过,谢谢。
【解决方案3】:

科学的正确答案是:你不能通过这段代码来判断。

更具建设性的答案是: 您必须确保在任何给定时间只有 一个 IndexWriter 正在写入索引,因此您需要一些机制来确保这一点。所以我的答案取决于你想要完成什么:

  • 您想更深入地了解 Lucene 吗?或者..
  • 您只想构建和使用索引吗?

如果你回答是后者,你可能想看看Solr之类的项目,它隐藏了所有的索引读写。

【讨论】:

  • 我只想构建和使用索引,不想使用 Solr。我将研究多个 IndexWriters。
【解决方案4】:

这个问题可能与 Too many open files Error on Lucene

我在这里重复我的答案。

使用复合索引来减少文件数。设置此标志时,lucene 会将一个段写入单个 .cfs 文件而不是多个文件。这将显着减少文件数量。

IndexWriter.setUseCompoundFile(true)

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2011-09-06
  • 2017-09-09
  • 1970-01-01
  • 2011-06-29
  • 2011-09-10
  • 2011-05-16
  • 1970-01-01
相关资源
最近更新 更多