Java Lucene性能:将字段数据从一个索引传输到另一个索引

Java Lucene性能:将字段数据从一个索引传输到另一个索引,java,search,lucene,Java,Search,Lucene,简而言之,我需要交换从一个索引到结果索引的多个字段和值的映射 以下是场景 指数1结构 [字段=>值][存储] Doc 1 keys => keyword1; Ids => id1, id1, id2, id3, id7, id11, etc.. Doc 2 keys => keyword2; Ids => id3, id11, etc.. Doc 1 ids => id1 keys => keyword1,

简而言之,我需要交换从一个索引到结果索引的多个字段和值的映射

以下是场景

指数1结构 [字段=>值][存储]

Doc 1    
keys => keyword1;    
Ids => id1, id1, id2, id3, id7, id11, etc.. 

Doc 2    
keys => keyword2;    
Ids => id3, id11, etc..
Doc 1    
ids => id1    
keys => keyword1, keyword1

Doc 3    
ids => id3    
keys => keyword1, keyword2, etc..
指数2结构 [字段=>值][存储]

Doc 1    
keys => keyword1;    
Ids => id1, id1, id2, id3, id7, id11, etc.. 

Doc 2    
keys => keyword2;    
Ids => id3, id11, etc..
Doc 1    
ids => id1    
keys => keyword1, keyword1

Doc 3    
ids => id3    
keys => keyword1, keyword2, etc..
请注意,结果索引中的keysid映射是反向的

就时间复杂性而言,您认为最有效的方法是什么

我能想到的唯一办法是

1) index1Reader.terms();    
2) Process only terms belonging to "Ids" field    
3) For each term, get TermDocs    
4) For each doc, load it, get "keys" field info    
5) Create a new Lucene Doc, add 'Id', multi Keys, write it to index2.     
6) Go to step 2.
由于字段是存储的,我确信有多种方法可以实现这一点

请指导我任何表演技巧考虑到Index1的大小约为6GB,即使是最微小的改进都会对我的场景产生巨大影响

唯一关键词总数:1800万; 唯一ID总数:90万

有趣的更新

优化1

  • 在添加新文档时,与其创建多个重复的“字段”对象,不如使用“”分隔符创建单个StringBuffer,然后将整个添加为单个字段,这样似乎可以提高25%
更新2:代码

    public void go() throws IOException, ParseException {
    String id = null;
    int counter = 0;
    while ((id = getNextId()) != null) { // this method is not taking time..
        System.out.println("Node id: " + id);
        updateIndex2DataForId(id);
        if(++counter > 10){
            break;
        }
    }
    index2Writer.close();
}

private void updateIndex2DataForId(String id) throws ParseException, IOException {
    // Get all terms containing the node id
    TermDocs termDocs = index1Reader.termDocs(new Term("id", id));
    // Iterate
    Document doc = new Document();
    doc.add(new Field("id", id, Store.YES, Index.NOT_ANALYZED));
    int docId = -1;        
    while (termDocs.next()) {
        docId = termDocs.doc();
        doc.add(getKeyDataAsField(docId, Store.YES, Index.NOT_ANALYZED));            
    }
    index2Writer.addDocument(doc);
}

private Field getKeyDataAsField(int docId, Store storeOption, Index indexOption) throws CorruptIndexException,
        IOException {
    Document doc = index1Reader.document(docId, fieldSelector); // fieldSel has "key"
    Field f = new Field("key", doc.get("key"), storeOption, indexOption);
    return f;
}

FieldCache的使用非常有效。。。但是,我们需要分配越来越多的RAM来容纳堆上的所有字段

我已经用以下代码段更新了上面的updateIndex2DataForId()

private void updateIndex2DataForId(String id) throws ParseException, IOException {
    // Get all terms containing the node id
    TermDocs termDocs = index1Reader.termDocs(new Term("id", id));
    // Iterate
    Document doc = new Document();
    doc.add(new Field("id", id, Store.YES, Index.NOT_ANALYZED));
    int docId = -1;
    StringBuffer buffer = new StringBuffer();
    while (termDocs.next()) {
        docId = termDocs.doc();
        buffer .append(keys[docId] + " "); // keys[] is pre-populated using FieldCache                 
    }
    doc.add(new Field("id", buffer.trim().toString(), Store.YES, Index.ANALYZED));   
    index2Writer.addDocument(doc);
}

String[] keys = FieldCache.DEFAULT.getStrings(index1Reader, "keywords");
它使一切都更快了,我不能告诉你确切的指标,但我必须说,非常重要


现在,该计划将在一段合理的时间内完成。无论如何,我们高度赞赏进一步的指导

这只是一次吗?我的猜测是,花在思考这个问题上的时间将超过优化所节省的时间。。。6gb是一个很大的索引,但是lucene可以很快地处理这些东西。。。你有没有做过暴力测试,看看需要多长时间?谢谢你的回复。虽然这是一次性的,但我可能要在截止日期前做几次。因此,考虑性能改进。是的,我试过上述方法,时间消耗有点令人失望。每个文档需要几秒钟(2-5+)的时间。预期的文档总数高达100万。您分析了这么长时间的原因是什么?还不确定,加载文档可能是一个潜在的罪魁祸首。。我应该只加载“关键字”,在这种情况下,我可以避免加载非常长的“ID”字段。@phani wow!每个文档都有几秒钟的时间真是太离谱了。。。不应该这么慢。你能发布一些你正在使用的代码让我们看看吗。甚至没有想过使用fieldcache。。。是的,我可以想象,只有3gb,你还需要多一点才能让这个尖叫声继续下去。