2010-09-30 64 views
8

我试图原型,使用非常不稳定索引的数据源(论坛,社交网络等)的索引/搜索应用,这里有一些性能要求,如何处理非常频繁地更新Lucene索引

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

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

  3. 最后但并非最不重要的一点,搜索应用程序需要有响应。 (100毫秒数量级上的延迟,并至少应支持10 QPS)

所有的我都可以当前/可满足W 0使用Lucene的要求(这将让我满足所有1,2和3),但我期待着未来的其他需求(比如搜索相关性等),Lucene更容易实现。不过,由于Lucene的设计目标远比我目前正在使用的更复杂,所以我很难满足我的性能要求。

这里有一些问题,

a。我读过IndexWriter类中的optimize()方法很昂贵,不应该被频繁更新的应用程序使用,有什么选择?

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

c。我知道Lucene提供了一种删除方法,它可以让你删除所有匹配某个查询的文档,在我的情况下,我需要删除所有年龄大于某个特定年龄的文档,现在有一种方法是为每个文档添加一个日期字段文档并用它来稍后删除文档。是否可以对文档ID进行范围查询(我可以创建自己的ID字段,因为我认为由lucene创建的字段不断更改)删除文档?比比较表示为字符串的日期更快吗?

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

回答

0

答:我认为最新版本的Lucene并没有真正需要优化方法,并且对于我对C项的建议,它确实不应该被需要。 B:再次,我认为最新版本的Lucene,搜索者知道何时更新完成,并且可以处理,而不需要做任何特别的事情。 C:我会避免删除,只是每天创建一个新的索引。如果将文档的年龄存储在索引中,则可以使用现有索引创建新索引。在索引编写过程中,获取所有年轻文档,遍历它们并将它们添加到新索引中。有一个名为getCurrentIndex的公共实用方法,搜索者使用它来获取最新的实时索引。为了以防万一,保留1或2个旧索引,你应该很好。

3

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

就范围查询而言,Solr具有TrieField功能,这使得数值范围查询超快。请参阅http://www.lucidimagination.com/blog/2009/05/13/exploring-lucene-and-solrs-trierange-capabilities/

5

Lucene现在支持Near Real Time Search。从本质上讲,每次你进行搜索时,你都会从IndexWriter获得一个Reader。内存更改不会到达磁盘,直到达到RAM缓冲区大小,或者在写入程序上调用明确的commit。由于跳过commit可避免磁盘IO,即使使用新数据,搜索也会快速返回。

Lucene的NRT麻烦之一是索引对数合并算法。将10个文档添加到细分后触发合并。接下来,将这10个段合并为一个包含100个文档的段,等等。现在,如果您有999,999个文档,并且触发了合并,则需要一段时间才能返回,从而打破您的“实时”承诺。

LinkedIn已发布Zoie,这是一个解决此问题的Lucene之上的库。这是现场直播,每天处理数百万次更新和搜索。

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

0

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