【问题标题】:java - MongoDB + Solr performancesjava - MongoDB + Solr 性能
【发布时间】:2011-11-03 20:45:50
【问题描述】:

我一直在四处寻找如何将 MongoDB 与 Solr 结合使用,这里的一些问题有部分答案,但没有什么真正具体的(更像是理论)。在我的应用程序中,我将在 MongoDB 中存储大量文档(可能多达几亿),并且我想对这些文档的某些属性实现全文搜索,所以我想 Solr 是最好的方法这个。

我想知道的是我应该如何配置/执行一切以使其具有良好的性能?现在,这就是我所做的(我知道它不是最佳的):

1- 在 MongoDB 中插入对象时,我将其添加到 Solr

SolrServer server = getServer();
SolrInputDocument document = new SolrInputDocument();
document.addField("id", documentId);
...
server.add(document);
server.commit();

2- 更新对象的属性时,由于 Solr 不能只更新一个字段,所以我首先从 MongoDB 检索对象,然后使用对象和新属性的所有属性更新 Solr 索引,并执行类似的操作

StreamingUpdateSolrServer update = new StreamingUpdateSolrServer(url, 1, 0);
SolrInputDocument document = new SolrInputDocument();
document.addField("id", documentId);
...
update.add(document);
update.commit();

3- 查询时,首先查询 Solr,然后在检索文档列表时 SolrDocumentList 遍历每个文档并:

  1. 获取文档的id
  2. 从 MongoDB 中获取具有相同 id 的对象,以便能够从那里检索属性

4- 删除时,我还没有完成那部分,也不确定如何在 Java 中完成

那么对于此处描述的每个场景,有人对如何以更有效的方式执行此操作有建议吗?喜欢在 Solr 中拥有大量文档并一次添加一个文档时不需要 1 小时即可重建索引的过程?我的要求是用户可能希望多次添加一个文档,我希望他们能够在之后立即检索它

【问题讨论】:

  • 每个文档有多大以及要索引的属性?
  • @JustinThomas - 每个文档可以有大约 10 个属性,其中一些可能是很长的描述,我想索引描述的全文搜索,只是精确匹配其他的.这能回答你的问题吗?

标签: java mongodb solr


【解决方案1】:

您的方法实际上很好。一些流行的框架(如 Compass)正在执行您在较低级别描述的内容,以便自动镜像到通过 ORM 框架执行的索引更改(请参阅http://www.compass-project.org/overview.html)。

除了您所描述的之外,我还会定期重新索引 MongoDB 中的所有数据,以确保 Solr 和 Mongo 都同步(可能没有您想象的那么长,具体取决于数量文档的数量、字段的数量、每个字段的令牌数量和分析器的性能:我经常使用复杂的分析器在不到 15 分钟的时间内创建从 5 到 8 百万个文档(大约 20 个字段,但文本字段很短)的索引,只需确保您的 RAM 缓冲区不会太小,并且在添加所有文档之前不要提交/优化)。

关于性能,提交代价高昂,优化代价高昂。根据对您最重要的因素,您可以更改 Solrconfig.xml 中 mergefactor 的值(高值可提高写入性能,而低值可提高读取性能,从 10 开始是一个不错的值)。

您似乎害怕索引构建时间。但是,由于 Lucene 索引存储是基于段的,因此写入吞吐量不应过多地依赖于索引的大小 (http://lucene.apache.org/java/2_3_2/fileformats.html)。但是,预热时间会增加,所以你应该确保

  • 在您的 solrconfig.xml 配置文件中的 firstSearcher 和 newSearcher 参数中有典型的(尤其是为了加载字段缓存的排序)但不太复杂的查询,
  • useColdSearcher 设置为
    • false 以获得良好的搜索性能,或
    • 如果您希望以较慢的搜索为代价更快地考虑对索引执行的更改,则为 true。

此外,如果您可以接受数据在写入 MongoDB 后仅几 X 毫秒即可搜索,您可以使用 UpdateHandler 的 commitWithin 功能。这样,Solr 将不得不减少提交频率。

有关 Solr 性能因素的更多信息,请参阅 http://wiki.apache.org/solr/SolrPerformanceFactors

要删除文档,您可以按文档 ID(如 schema.xml 中定义)或查询删除: http://lucene.apache.org/solr/api/org/apache/solr/client/solrj/SolrServer.html

【讨论】:

  • deleteById 的好点,我实际上没有看到它(我什至没有尝试我必须说,我认为有更复杂的东西)。既然您似乎对此了解很多,如果您不介意的话,再问几个问题: 1. 一个好的 RAM 缓冲区是多少? 2.我没有更改示例solrconfig.xml文件的firstSearcher和newSearcher,它们好吗? 3.最后,我有一个在tomcat下运行的solr实例,里面有5个核心。它是否会改变有关性能的任何内容以运行多个 solr 实例?谢谢你的帮助
  • 1.您需要执行一些基准测试以找到最佳缓冲区大小。我建议您从 32M 开始,并在每次迭代时将可用于 RAM 缓冲区的内存量加倍,当增加 ram 缓冲区大小不会产生任何显着改进时停止。
  • 2.它们不是:使用 Solr 加载字段缓存(排序和函数查询等需要)需要时间,因此,将在新索引上使用字段缓存的第一个查询将有性能损失,因此您需要放置查询这将在 newSearcher 和 firstSearcher 中加载这些字段缓存(只需放置一个查询,它对与您的应用程序相同的字段执行排序)。
  • 3.我认为最好只运行一个实例:一些内存将在内核之间共享,因此所需的全局内存量会更低,为操作系统的 I/O 缓存留出更多内存,这是一个非常Solr 的重要性能因素:java.dzone.com/news/os%E2%80%99s-cache-does-matter-query
【解决方案2】:
  1. 您还可以等待更多文档,然后每隔 X 分钟对它们进行索引。 (当然这在很大程度上取决于您的应用程序和要求)

  2. 如果您的文档很小并且您不需要所有数据(存储在 MongoDB 中),您可以通过存储而不是索引仅将您需要的字段放入 Solr 文档中

    李>

<field name="nameoyourfield" type="stringOrAnyTypeYouuse"索引="false"已存储="true"/>

【讨论】:

    猜你喜欢
    • 2015-11-26
    • 1970-01-01
    • 1970-01-01
    • 2013-08-16
    • 2017-03-06
    • 2016-10-30
    • 2017-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多