浏览 1005 次
|
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2007-06-05 关键字: IndexWriter类addDocument效率问题
IndexWriter类的方法:
public void addDocument(Document doc, Analyzer analyzer) throws IOException { SegmentInfo newSegmentInfo = buildSingleDocSegment(doc, analyzer); synchronized (this) { ramSegmentInfos.addElement(newSegmentInfo); maybeFlushRamSegments(); } } 执行效率很慢,当我只是把ramSegmentInfos.addElement(newSegmentInfo);这句注释後就很快(效率相差很大)。当只是把maybeFlushRamSegments();这句注释掉,效率依然很慢。 所以 总的来说应该是ramSegmentInfos.addElement(newSegmentInfo);这句很占用效率,不知道怎么解释。该怎么解决呢?非常感谢。 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2007-06-05
应该说你的业务中核心是
ramSegmentInfos.addElement(newSegmentInfo); 而flushRam只是把内存清一下。。。。 你说你的核心逻辑效率差。。。。 又没给出你的数据, 也没给出你的理想值, 更没有测试用例。。。。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-06-05
功能:首先向RAMDirectory里写,当达到1000个Document後,再向FSDirectory里写。
当多线程执行时,会大量报java.lang.NullPointerException,有没有好的解决办法? 自己写的多线程索引的类为(IndexWriterServer,该对象只在Server启动时初始化一次):
public class IndexWriterServer{
private static IndexWriter indexWriter = null;
//private String indexDir ;//索引目录;
private static CJKAnalyzer analyzer = null;
private static RAMDirectory ramDir = new RAMDirectory();
private static IndexWriter ramWriter = null;
private static int diskFactor = 0;//内存中现在有多少Document
private static long ramToDistTime = 0;//内存向硬盘写需要多少时间
private int initValue = 1000;//内存中达到多少Document,才向硬盘写
private static IndexItem []indexItems = null;
public IndexWriterServer(String indexDir){
initIndexWriter(indexDir);
}
public void initIndexWriter(String indexDir){
boolean create = false;//是否创建新的
analyzer = new CJKAnalyzer();
Directory directory = this.getDirectory(indexDir);
//判断是否为索引目录
if(!IndexReader.indexExists(indexDir)){
create = true;
}
indexWriter = getIndexWriter(directory,create);
try{
ramWriter = new IndexWriter(ramDir, analyzer, true);
}catch(Exception e){
logger.info(e);
}
indexItems = new IndexItem[initValue+2];
}
/**
* 生成单个Item索引
*/
public boolean generatorItemIndex(IndexItem item, Current __current) throws DatabaseError, RuntimeError{
boolean isSuccess = true;//是否索引成功
try{
Document doc = getItemDocument(item);
ramWriter.addDocument(doc);//关键代码,错误就是从这里报出来的
indexItems[diskFactor] = item;//为数据挖掘使用
diskFactor ++;
if((diskFactor % initValue) == 0){
ramToDisk(ramDir,ramWriter,indexWriter);
//ramWriter = new IndexWriter(ramDir, analyzer, true);
diskFactor = 0;
//数据挖掘
isSuccess = MiningData();
}
doc = null;
logger.info("generator index item link:" + item.itemLink +" success");
}catch(Exception e){
logger.info(e);
e.printStackTrace();
logger.info("generator index item link:" + item.itemLink +" faiture");
isSuccess = false;
}finally{
item = null;
}
return isSuccess;
}
public void ramToDisk(RAMDirectory ramDir, IndexWriter ramWriter,IndexWriter writer){
try{
ramWriter.close();//关键代码,把fileMap赋值为null了
ramWriter = new IndexWriter(ramDir, analyzer, true);//重新构建一个ramWriter对象。因为它的fileMap为null了,但是好像并没有太大作用
Directory ramDirArray[] = new Directory[1];
ramDirArray[0] = ramDir;
mergeDirs(writer, ramDirArray);
}catch(Exception e){
logger.info(e);
}
}
/**
* 将内存里的索引信息写到硬盘里
* @param writer
* @param ramDirArray
*/
public void mergeDirs(IndexWriter writer,Directory[] ramDirArray){
try {
writer.addIndexes(ramDirArray);
//optimize();
} catch (IOException e) {
logger.info(e);
}
}
}
主要原因大概是因为:在调用ramWriter.close();时,Lucene2.1里RAMDirectory 的close()方法 public final void close() {
fileMap = null;
}
把fileMap 给置null了,当多线程执行ramWriter.addDocument(doc);时,最终执行RAMDirectory 的方法: public IndexOutput createOutput(String name) {
RAMFile file = new RAMFile(this);
synchronized (this) {
RAMFile existing = (RAMFile)fileMap.get(name);//fileMap为null,所以报:NullPointerException,
if (existing!=null) {
sizeInBytes -= existing.sizeInBytes;
existing.directory = null;
}
fileMap.put(name, file);
}
return new RAMOutputStream(file);
}
提示:在网上搜索了一下,好像这个是lucene的一个bug(http://www.opensubscriber.com/message/java-user@lucene.apache.org/6227647.html),但是好像并没有给出解决方案。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-06-05
建议用监控线程来维护merge indeces、IndexWriter的instances,工作线程仅仅提供劳动力,一个thread维护一个IndexWriter的instance,应该可以避免类似的问题。
SegmentInfo继承自Vector,这意味着SegmentInfo的大部分操作是同步的,多线程操作SegmentInfo基本没有多少性能提升,没做过这个实验,提供这个思路给楼主参考一下。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-06-07
谢谢指点
|
|
| 返回顶楼 | |








