【发布时间】:2014-06-05 17:01:27
【问题描述】:
我正在我的应用程序中测试 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 的目标不是减速 450 倍,关于我应该在哪里寻找提示的任何建议?
更多信息:我不会在减速期间调用优化,并且“偶尔”即使在建立索引时我也会得到一个快速的答案,但当这种情况发生时它似乎很随机。我确实偶尔会调用一次提交(每 100 次插入)。
【问题讨论】:
-
如果您在运行索引时得到不同的响应时间,那么我怀疑您是否在 NRT 中。
-
实际上我发现了一些非常时髦的东西,如果我删除所有优化/提交的调用,那么索引会保留在 1 个文件中并不断增长(这是预期的行为),但是一旦我启动搜索,它分裂了,好像提交被强制了,有什么可能导致这种情况的线索吗?只有我链接的代码在搜索过程中被调用,它所做的一切都是由作者使用阅读器提供程序读取的,建议执行 NRT
-
这段代码是否适合确定与索引同时进行的搜索性能?它将读取索引中的每个文档,以及每个文档的每个字段;在您的应用程序中可能永远不需要这些。许多场景只需要最多说 50 个搜索结果。如果索引未更改,则文档可能位于 I/O 缓存中并且可用速度非常快(first 搜索速度较慢)。如果更改了索引,则必须从磁盘重新加载文档 - 比缓存慢得多。
-
它是相关的,是的,我确实显示了 1000 个搜索结果(它不是用于搜索引擎分页的 web 应用程序,而是用于具有高级预览的完整搜索客户端,人们可能想看看几百个结果)
-
虽然我没有给你一个规范的答案,但有一些建议。您的测试代码为搜索找到的每个 docID 调用
IndexReader.Document:尝试加载 only docID 的列表(例如,IndexSearcher.Search的另一个重载返回ScoreDoc[])。然后只加载足够的IndexableItem对象以填满您的高级预览的一屏(或两屏);对此进行测试以查看“按需加载”策略是否产生所需的性能。如果是这样,您可以延迟加载剩余的IndexableItem对象,或者将高级预览实现为虚拟列表,即。 “按需加载”。
标签: c# .net lucene lucene.net