如何有效地(即 w/o 内存泄漏)检索 Solr 索引中已经存在的文档?
How to efficiently (ie w/o memory leaks) retrieve already exising documents in a Solr index?
我认为我的方法正在泄漏内存,因为在探查器中 "Surviving generations" 的数量不断增加:
在生产中,我在一段时间后收到 "OOM heap space" 错误,现在我认为我的方法是罪魁祸首。
作为背景,我的方法目标是检索索引中已经存在的文档。然后使用该列表来判断文档是否可以保留在索引中或可以删除(例如,相应的文档已从磁盘中删除):
public final List<MyDocument> getListOfMyDocumentsAlreadyIndexed() throws SolrServerException, HttpSolrClient.RemoteSolrException, IOException {
final SolrQuery query = new SolrQuery("*:*");
query.addField("id");
query.setRows(Integer.MAX_VALUE); // we want ALL documents in the index not only the first ones
SolrDocumentList results = this.getSolrClient().
query(
query).getResults();
listOfMyDocumentsAlreadyIndexed = results.parallelStream() // tried to replace with stream with the same behaviour
.map((doc) -> {
MyDocument tmpDoc = new MyDocument();
tmpDoc.setId((String) doc.getFirstValue(
"id"));
// Usually there are things done here to set some boolean fields
// that I have removed for the test and this question
return tmpDoc;
})
.collect(Collectors.toList());
return listOfMyDocumentsAlreadyIndexed;
}
此方法的测试在 for 循环中执行以下调用 300 次(这模拟了索引循环,因为我的程序一个接一个地索引索引):
List<MyDocument> listOfExistingDocsInIndex = index.getListOfMyDocumentsAlreadyIndexed();
我试过用完后作废(测试没用,就是看看有没有效果),没有明显变化:
listOfExistingDocsInIndex = null;
这是我从 Netbeans 探查器获得的调用树(我刚刚开始使用探查器):
我可以更改/改进什么来避免此内存泄漏(这实际上是内存泄漏,不是吗?)?
感谢任何帮助:-),
到目前为止,我发现要避免在从索引中检索所有文档时发生内存泄漏,必须避免使用 :
query.setRows(Integer.MAX_VALUE);
取而代之的是,必须按块大小所在的块来逐块检索文档 between 100 and 200 documents as depicted in Solr's wiki :
SolrQuery q = (new SolrQuery(some_query)).setRows(r).setSort(SortClause.asc("id"));
String cursorMark = CursorMarkParams.CURSOR_MARK_START;
boolean done = false;
while (! done) {
q.set(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);
QueryResponse rsp = solrServer.query(q);
String nextCursorMark = rsp.getNextCursorMark();
doCustomProcessingOfResults(rsp);
if (cursorMark.equals(nextCursorMark)) {
done = true;
}
cursorMark = nextCursorMark;
}
现在幸存的世代随着时间的推移保持稳定:
缺点是垃圾收集器更活跃,检索速度更慢(我没有对它进行基准测试,所以我没有指标可以显示)。
我认为我的方法正在泄漏内存,因为在探查器中 "Surviving generations" 的数量不断增加:
在生产中,我在一段时间后收到 "OOM heap space" 错误,现在我认为我的方法是罪魁祸首。
作为背景,我的方法目标是检索索引中已经存在的文档。然后使用该列表来判断文档是否可以保留在索引中或可以删除(例如,相应的文档已从磁盘中删除):
public final List<MyDocument> getListOfMyDocumentsAlreadyIndexed() throws SolrServerException, HttpSolrClient.RemoteSolrException, IOException {
final SolrQuery query = new SolrQuery("*:*");
query.addField("id");
query.setRows(Integer.MAX_VALUE); // we want ALL documents in the index not only the first ones
SolrDocumentList results = this.getSolrClient().
query(
query).getResults();
listOfMyDocumentsAlreadyIndexed = results.parallelStream() // tried to replace with stream with the same behaviour
.map((doc) -> {
MyDocument tmpDoc = new MyDocument();
tmpDoc.setId((String) doc.getFirstValue(
"id"));
// Usually there are things done here to set some boolean fields
// that I have removed for the test and this question
return tmpDoc;
})
.collect(Collectors.toList());
return listOfMyDocumentsAlreadyIndexed;
}
此方法的测试在 for 循环中执行以下调用 300 次(这模拟了索引循环,因为我的程序一个接一个地索引索引):
List<MyDocument> listOfExistingDocsInIndex = index.getListOfMyDocumentsAlreadyIndexed();
我试过用完后作废(测试没用,就是看看有没有效果),没有明显变化: listOfExistingDocsInIndex = null;
这是我从 Netbeans 探查器获得的调用树(我刚刚开始使用探查器):
我可以更改/改进什么来避免此内存泄漏(这实际上是内存泄漏,不是吗?)?
感谢任何帮助:-),
到目前为止,我发现要避免在从索引中检索所有文档时发生内存泄漏,必须避免使用 :
query.setRows(Integer.MAX_VALUE);
取而代之的是,必须按块大小所在的块来逐块检索文档 between 100 and 200 documents as depicted in Solr's wiki :
SolrQuery q = (new SolrQuery(some_query)).setRows(r).setSort(SortClause.asc("id"));
String cursorMark = CursorMarkParams.CURSOR_MARK_START;
boolean done = false;
while (! done) {
q.set(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);
QueryResponse rsp = solrServer.query(q);
String nextCursorMark = rsp.getNextCursorMark();
doCustomProcessingOfResults(rsp);
if (cursorMark.equals(nextCursorMark)) {
done = true;
}
cursorMark = nextCursorMark;
}
现在幸存的世代随着时间的推移保持稳定:
缺点是垃圾收集器更活跃,检索速度更慢(我没有对它进行基准测试,所以我没有指标可以显示)。