如何处理Lucene索引的频繁更新

时间:2010-09-30 21:15:58

标签: performance indexing lucene

我正在尝试使用非常不稳定的索引数据源(论坛,社交网络等)对索引/搜索应用程序进行原型设计,这里有一些性能要求,

  1. 非常快的周转时间(我的意思是,很快就会在搜索结果中显示任何新数据(例如论坛上的新消息)(不到一分钟))

  2. 我需要定期丢弃旧文件,以确保搜索结果没有过时。

  3. 最后但并非最不重要的是,搜索应用程序需要响应。 (延迟大约100毫秒,并且应该支持至少10 qps)

  4. 我目前所有的要求都可以使用Lucene来满足(这将让我满足所有1,2和3),但我期待未来的其他要求(如搜索相关性等)Lucene使实施更容易。但是,由于Lucene的设计用于比我目前正在使用的用例复杂得多的用例,因此我很难满足我的性能要求。

    以下是一些问题,

    一个。我读到IndexWriter类中的optimize()方法很昂贵,不应该被频繁更新的应用程序使用,有哪些替代方案?

    湾为了进行增量更新,我需要不断提交新数据,并且还要不断刷新索引阅读器以确保它具有新数据。这些将影响上面的1和3。我应该尝试重复索引吗?有哪些常见方法可以解决这个问题?

    ℃。我知道Lucene提供了一个删除方法,它允许你删除所有匹配某个查询的文档,在我的情况下,我需要删除所有早于某个年龄的文档,现在一个选项是为每个文件添加一个日期字段记录并使用它来删除文档。是否可以对文档ID进行范围查询(我可以创建自己的id字段,因为我认为由lucene创建的字段不断变化)来删除文档?它比比较表示为字符串的日期更快吗?

    我知道这些是非常开放的问题,所以我不是在寻找详细的答案,我会尽力将你的所有答案视为建议并用它们来告知我的设计。谢谢!如果您需要任何其他信息,请与我们联系。

4 个答案:

答案 0 :(得分:6)

Lucene现在支持Near Real Time Search。从本质上讲,每次进行搜索时,都会从IndexWriter获得一个Reader。在达到RAM缓冲区大小或在编写器上调用显式commit之前,内存中的更改不会进入磁盘。通过跳过commit可以避免磁盘IO,即使使用新数据,搜索也会快速返回。

Lucene的NRT的一个问题是索引对数合并算法。将10个文档添加到段后触发合并。接下来,合并这样的10个片段以创建具有100个文档的片段,依此类推。现在,如果您有999,999个文档,并且触发了合并,则返回将需要相当长的时间,从而打破您的“实时”承诺。

LinkedIn发布了Zoie,一个位于Lucene之上的图书馆解决了这个问题。这是生产中的每天处理数百万次更新和搜索。

大多数情况下,Lucene会支持您的所有要求,因为您丢弃了旧的更新,并且移动窗口的大小基本不变。如果没有,你可能需要尝试在战场上证明的Zoie。

答案 1 :(得分:4)

你可能想考虑使用Solr而不是直接使用Lucene。 Solr处理您提到的所有要求(近实时更新,删除文档,性能/分片,范围查询),并且它比您自己的手动代码更好。您不必处理IndexReader级别的问题,即何时在更新后刷新IndexReader。

就范围查询而言,Solr具有TrieField功能,可以使数字范围查询超快。见http://www.lucidimagination.com/blog/2009/05/13/exploring-lucene-and-solrs-trierange-capabilities/

答案 2 :(得分:0)

答:我认为使用最新版本的Lucene,并不需要优化方法,而且根据我对项目C的建议,确实不需要它。

B:再次,我认为使用最新版本的Lucene,搜索者会知道何时完成更新并且可以在不需要做任何特殊操作的情况下处理。

C:我会避免删除,只是每天创建一个新索引。如果将文档的年龄存储在索引中,则可以使用现有索引创建新索引。在索引编写期间,获取所有年轻文档,浏览它们并将它们添加到新索引中。有一个名为getCurrentIndex的公共util方法,搜索者使用它来获取最新的实时索引。保留1或2个旧索引以防万一,你应该好好去。

答案 3 :(得分:0)

您可以在短时间内缓存索引搜索器并重新打开它。我们为此目的使用asp.net WebCache,它具有在chached项目到期之前调用的CacheItemUpdateCallback。