有谁知道为什么会这样?我正在对XML文件进行基本索引+ SAX解析,并将每个路径添加为文档中的新字段。我喜欢150万个文件,它在这个文件上停留30分钟,而.nrm(规范化文件??)变得越来越大。
我不知道为什么会这样,我的IndexWriter的形式如下:
writer = new IndexWriter(dir, new StandardAnalyzer(Version.LUCENE_30), IndexWriter.MaxFieldLength.UNLIMITED)
这对于大型指数来说不是最佳的吗?为什么它冻结在这个文件上?我已经多次使用超过100万个XML文件运行它,并且它不断地卡在不同的XML文件上(特别是这个文件 - 结构很好)。
编辑:
因此,假设我使用单独的java命令一次索引文件2000。索引编写完成后我调用indexwriter close方法,如果我想重写这个索引,我是否遗漏了什么?我应该优化指数吗?我想我记得Lucene in Action说要优化一段时间你是否会写它。
实际上,这种方法适用于180万个文件,但在我尝试在2000个批量添加更多文件后,这个NRM文件和另一个文件写入了大约70GB!如果仅在2000次批量调用java Lucene索引函数时,为什么内存会从JVM中耗尽?它看起来不像垃圾收集问题,除非我在关闭索引编写器之前需要在Lucene代码中添加一些内容。
编辑2:
我有大约400万个XML文件,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<person>
<name>Candice Archie
</name>
<filmography>
<direct>
<movie>
<title>Lucid (2006) (V)
</title>
<year>2006
</year>
</movie>
</direct>
<write>
<movie>
<title>Lucid (2006) (V)
</title>
<year>2006
</year>
</movie>
</write>
<edit>
<movie>
<title>Lucid (2006) (V)
</title>
<year>2006
</year>
</movie>
</edit>
<produce>
<movie>
<title>Lucid (2006) (V)
</title>
<year>2006
</year>
</movie>
</produce>
</filmography>
</person>
我解析这些XML文件并将内容添加到路径的字段中,例如/ person / produce / filmography / movie / title,Lucid(2006)(V)
问题是,我希望计算文档字段实例中给定术语的频率统计数据,对于索引中的每个文档(然后在所有文档上对该值求和)...所以如果有的话/ person / produce / filmography / movie / title的两个实例,它们都包含“Lucid”,我想要两个。如果有另一条路径(例如:/ person / name:Lucid),则Lucene给出的tf(t in d)将给出3,但是对于文档中类似字段内的术语不会这样做。
Lucene Indexing的核心是这样做:
public void endElement( String namespaceURI,String localName,String qName ) throws SAXException {
if(this.ignoreTags.contains(localName)){
ignoredArea = false;
return;
}
String newContent = content.toString().trim();
if(!empty.equals(newContent) && newContent.length()>1)
{
StringBuffer stb = new StringBuffer();
for(int i=0; i<currpathname.size();i++){
//System.out.println(i + "th iteration of loop. value:" + currpathname.get(i).toString() + k + "th call.");
stb.append("/");
stb.append(currpathname.get(i));
}
//stb.append("0");
if(big.get(stb.toString())==null){
big.put(stb.toString(), 1);
}
else{
big.put(stb.toString(),big.get(stb.toString())+1);
}
if(map.get(stb.toString())==null){
map.put(stb.toString(),0);
stb.append(map.get(stb.toString())); //ADDED THIS FOR ZERO
}
else
{
map.put(stb.toString(),map.get(stb.toString())+1);
stb.append(map.get(stb.toString()));
}
doc.add(new Field(stb.toString(),newContent,Field.Store.YES, Field.Index.ANALYZED));
seenPaths.add(stb);
//System.out.println(stb.toString());// This will print all fields indexed for each document (separating nonunique [e.x.: /person/name0 /person/name1]
//System.out.println(newContent);
}
currpathname.pop();
content.delete(0,content.length()); //clear content
//This method adds to the Lucene index the field of the unfolded Stack variable currpathname and the value in content (whitespace trimmed).
}
Map和BigMap是哈希映射(不用担心bigmap,它用于其他东西。只要实例化新的XML文件(Document对象),就会实例化map。毕竟有一个方法endDocument()可以添加文件调用startElement,endElement和character方法(这些是Xerces Parser方法)
public void endDocument( ) throws SAXException {
try {
numIndexed++;
writer.addDocument(doc);
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
对不起,很长的帖子 - 谢谢你的帮助! 另外,我不认为服务器是问题。我一次运行了400万个文件的代码,即使我使用的是Xmx12000M Xms12000M,也会耗尽堆内存
它是一个功能强大的服务器,所以它绝对可以解决这个问题......
编辑3:
再次问好!谢谢,你是对的。 Lucene可能没有做到这一点。我们实际上会做其他实验,但我认为我借助你的想法和其他一些方法解决了这个问题。首先,我停止了对字段的规范化,并且多次缩小了索引的大小。另外,我使用了mergedocs和rambuffer方法并将它们加了起来。索引大大改善。我会用你的帮助标记问题的答案:)谢谢。
答案 0 :(得分:1)
尝试批量编制索引。波纹管代码应该让你知道如何做到这一点。另外,我建议您查看最新版的Lucene in Action。
很可能你正在重载垃圾收集器(假设没有很难找到的内存泄漏),这最终会导致你的内存不足错误。
private static final int FETCH_SIZE = 100;
private static final int BATCH_SIZE = 1000;
//Scrollable results will avoid loading too many objects in memory
ScrollableResults scroll = query.scroll(ScrollMode.FORWARD_ONLY);
int batch = 0;
scroll.beforeFirst();
while (scroll.next()) {
batch++;
index(scroll.get(0)); //index each element
if (batch % BATCH_SIZE == 0) {
//flushToIndexes(); //apply changes to indexes
//optimize();
//clear(); //free memory since the queue is processed
}
}