我在我的应用程序中测试NRT(近乎实时)搜索的性能,我得到了非常奇怪的结果。我使用此查询作为获取所有元素的示例(测试集非常小,因此获取所有元素应该不是问题,这是250个文件仅被索引,仅文本文件,总索引大小= 1.5MB,我需要支持的真实集合是多GB索引的数百个文件
这是让我担心的示例查询:
public static List<IndexableItem> GetAllElements()
{
var qp = new Lucene.Net.QueryParsers.QueryParser(Lucene.Net.Util.Version.LUCENE_29, "ProviderPath", analyzer);
qp.AllowLeadingWildcard = true;
var query = qp.Parse("*");
var searcher = new Lucene.Net.Search.IndexSearcher(reader);
List<IndexableItem> docs = new List<IndexableItem>();
searcher.Search(query, new SimpleHitCollector(docId =>
{
docs.Add(reader.Document(docId).ToIndexable());
}));
return docs;
}
你可以看到它非常简单。此查询的运行时间约为0.1秒,而索引未运行,但如果我在同一时间运行索引,则它会上升到。 。 。 。 45秒或更长时间!
reader变量是一个定义如下的属性:
public static IndexReader reader
{
get
{
return writer.GetReader();
}
}
作家:
static SearchIndexManager()
{
writer = new IndexWriter(FSDirectory.Open(@"C:\MyFolder"), analyzer, IndexWriter.MaxFieldLength.UNLIMITED);
}
性能问题肯定在lucene内(它位于hitcollector内,每个docs.Add行之间需要1秒钟)。 ToIndexable也不是问题(这是一个简单的方法,并且完全不依赖于索引器可以使用的任何东西(磁盘io等)。
我很确定那里出了问题,显然NRT的目标不是让450X减速,有关我应该寻找提示的地方的任何建议吗?
更多信息:我不会在减速期间调用优化,并且“偶尔”我即使在编制索引时也会得到快速回答但是当发生这种情况时它似乎很随机。我偶尔会调用commit(每100次插入)。
答案 0 :(得分:2)
据我了解,近实时搜索适用于已更改但尚未提交更改的索引,搜索时不会发生进一步更改。这是NRT的最佳使用方式,我并不意味着在索引的同时无法进行搜索。如果它们与索引同时发生,则搜索或读取不是最理想的。
考虑方法IndexReader.Reopen
。它的目的是获得一个新的读者,如果索引正在改变或自从获得IndexReader
的旧实例以来已经改变。因此,如果您继续使用旧实例,您可能会错过您应该找到的文档,并且您正在阅读“移动目标”,从而导致性能降低。
您写道:
索引保留在1个文件中并且不断增长(这是预期的行为),但是一旦我启动搜索,它就会像提交被强制一样分裂
当您从IndexReader
获得IndexWriter
时,它将刷新所有缓冲的更改 - 请注意,这不是提交。