【问题标题】:How to avoid Java OutOfMemoryMemory Java Heap Space in Apache Solr如何避免 Apache Solr 中的 Java OutOfMemoryMemory Java 堆空间
【发布时间】:2015-10-15 13:05:47
【问题描述】:

我对 Java 世界比较陌生,最近开始使用 Solr。 我在 Amazon t2.small 盒子上运行 Solr 5.2.1,它是单核和 2 gm RAM ubuntu 服务器。我使用 1gb 堆空间配置运行 Solr。 Solr 核心目前有 8M 文档,包含 15 个字段,其中 14 个仅为字符串 ID。另一个是 DateRange 字段类型。

搜索查询通常很长,通常在 15000-20000 个字符的范围内。这是由于过滤查询与 100 范围内的多个字段值一起使用。例如,

/select?fq=field1:("value-1"+OR+"value-2"+.......+OR+"value-n") , n ranges from 1000-2000

我将 Jetty 的 MaxURLLength 修改为 65535,这让我可以这样做。

早些时候,当文档数量

java.lang.OutOfMemoryError: Java heap space
    at org.apache.lucene.util.FixedBitSet.<init>(FixedBitSet.java:115)
    at org.apache.lucene.spatial.prefix.IntersectsPrefixTreeFilter$1.start(IntersectsPrefixTreeFilter.java:62)
    at org.apache.lucene.spatial.prefix.AbstractVisitingPrefixTreeFilter$VisitorTemplate.getDocIdSet(AbstractVisitingPrefixTreeFilter.java:130)
    at org.apache.lucene.spatial.prefix.IntersectsPrefixTreeFilter.getDocIdSet(IntersectsPrefixTreeFilter.java:57)
    at org.apache.lucene.search.Filter$1.scorer(Filter.java:95)
    at org.apache.lucene.search.Weight.bulkScorer(Weight.java:137)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:768)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:485)
    at org.apache.solr.search.SolrIndexSearcher.getDocSetNC(SolrIndexSearcher.java:1243)
    at org.apache.solr.search.SolrIndexSearcher.getPositiveDocSet(SolrIndexSearcher.java:926)
    at org.apache.solr.search.SolrIndexSearcher.getProcessedFilter(SolrIndexSearcher.java:1088)
    at org.apache.solr.search.SolrIndexSearcher.getDocListNC(SolrIndexSearcher.java:1609)
    at org.apache.solr.search.SolrIndexSearcher.getDocListC(SolrIndexSearcher.java:1485)
    at org.apache.solr.search.SolrIndexSearcher.search(SolrIndexSearcher.java:561)
    at org.apache.solr.handler.component.QueryComponent.process(QueryComponent.java:518)
    at org.apache.solr.handler.component.SearchHandler.handleRequestBody(SearchHandler.java:255)
    at org.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:143)
    at org.apache.solr.core.SolrCore.execute(SolrCore.java:2064)
    at org.apache.solr.servlet.HttpSolrCall.execute(HttpSolrCall.java:654)
    at org.apache.solr.servlet.HttpSolrCall.call(HttpSolrCall.java:450)
    at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:227)
    at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:196)
    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
  1. 上述异常是内存不足造成的吗?
  2. 是因为查询太长而影响搜索吗?

【问题讨论】:

  • 1.是的。如果您阅读“OutOfMemoryError”这个词,您会发现这很明显。 2. 可能,但如果你分析你的应用程序,你就会确定。
  • 你的意思是个人资料 Solr?
  • JVM 的 -Xmx 设置是什么?你试过增加它吗?
  • @rudolfv -Xmx 设置为 1gb
  • @sravan_kumar 不,我的意思是描述您的应用程序。你不是在开发 Solr(我希望如此)。

标签: java solr lucene out-of-memory


【解决方案1】:

这可能与过滤器的数量有关:每个过滤器在索引中的每个文档使用 1 位。对于 8M 文档,每个过滤器使用 1MB。

如果您的 solrconfig.xml 中的 filterCache 部分来自示例,则其大小为 512。这意味着随着时间的推移,它将包含 512*1MB 的索引数据。使用 1GB 堆,它会耗尽内存听起来是合理的。

简单的解决方案是减少过滤器缓存中的条目数量。如果您的过滤器在呼叫之间是唯一的,这可能会对您的搜索速度产生负面影响,或者可能根本不会影响它。您必须对其进行测试。

https://wiki.apache.org/solr/SolrCaching#filterCache

【讨论】:

  • 感谢您的回复。现在我知道 Solr 中有不同类型的缓存。将使用不同的堆大小和缓存大小运行一组实验并检查行为。
  • 嘿,降低过滤器缓存有效!将对所需内存进行数学计算,然后移至更大的机器以获得更多内存。非常感谢!!
【解决方案2】:

如果您在 date 字段上进行过滤,那么使用 date range filter(代替具有 100 个值的布尔 OR)将从(I/O、CPU 和 内存 开销)每次查询扫描您的集合 100 次。

Solr 的TrieDateField 类型以某种方式(使用 Trie)进行索引,这样查找日期值在一个范围内的文档是一种廉价的操作(与迭代整个集合相比)。

如果您要查询过去 1000-2000 天内日期“在一天中的同一时间”的文档,请考虑在其自己的字段中单独编码一天中的时间(作为 int 可能会保存空间?),因此您可以先将过滤器集中在一天中的时间上,然后再消除 > 2000 天前的文档。

【讨论】:

  • 嘿,我已经在使用 DateRange 字段作为我的索引。除了这个过滤器,我还需要 4 个其他字符串过滤器,其中一个是具有数百个值的布尔过滤器。
  • 具有 100 个值的布尔过滤器仍然可能是处理过程中最昂贵的部分。阅读这篇有用的文章:未缓存过滤器(和 PostFilters)的cost 参数。 lucidworks.com/blog/2012/02/10/advanced-filter-caching-in-solr。您可能会发现,首先使用 cheap to execute 过滤器(日期范围和字符串匹配)减少搜索空间,然后会检查更昂贵的布尔过滤器(w 100s 个值) -频繁,从而降低查询的总成本。
猜你喜欢
  • 1970-01-01
  • 2018-07-22
  • 2017-11-08
  • 1970-01-01
  • 2011-09-21
  • 2021-09-09
  • 2015-07-06
  • 1970-01-01
  • 2016-04-17
相关资源
最近更新 更多