{过滤}比{查询} Lucene更快吗?

在阅读“Lucene in Action 2nd edition”时,我遇到了Filter类的描述,它可用于Lucene中的结果过滤。 Lucene有很多filter重复Query类。 例如, NumericRangeQueryNumericRangeFilter

该书说, NRFNRQ完全相同,但没有文件评分。 这是否意味着如果我不需要文档字段值对文档进行评分或排序,我应该更喜欢从性能角度Filter Query

我从Uwe Schindler那里得到了一个很好的答案,让我在这里重新发布。

如果你不缓存filter,查询会更快,因为Lucene中的ConjunctionScorer有优化,目前不用于filter。 如果缓存它们,filter就可以了(例如,如果对于应用于所有查询的特定用户,您始终具有相同的访问限制)。 在这种情况下,Filter仅执行一次并缓存所有其他请求,然后与查询结果集相交。

如果您只想例如随机“过滤”例如通过地理搜索中的可变数值范围(如边界框),使用查询,查询在大多数情况下更快(例如,范围查询和类似的东西 – 称为MultiTermQueries – 在内部也由与filter相同的BitSet算法 – 实际上它们只是由Scorer-impl包装的filter。 但是,将查询和“filter”查询进行AND运算的记分器(ConjunctionScorer)通常比搜索后应用filter的代码更快。 这可能会有一些改进,但一般情况下filter在Lucene中是不再需要的,因此已经有一些方法可以使filter和查询相同,而是能够缓存非评分查询。 这将使许多代码更容易。

filter可以带来Lucene 4.0的巨大速度提升,如果它们插入到IndexReader上以评分之前过滤文档,但是尚未实现(请参阅https://issues.apache.org/jira/browse/LUCENE-3212 ) – 我正在做。 我们也可以使filter随机访问(它很容易,因为它们是位集),这也可以改善后查询过滤。 但是,如果他们可以支持它(例如仅基于FieldCache的查询),我还会使查询部分随机访问。

乌韦

与Dennis的回答相反:不,您可能不想使用filter,除非您要多次重复使用相同的查询。

NumericRangeFilter只是MultiTermQueryWrapperFilter一个子类,这意味着它本质上是这样的:

 for each document in index: if document matches query: match[i] = 1 else match[i] = 0 

因此它将在索引上以线性时间运行,而不是像普通查询那样以对数时间运行。

此外,filter将占用更多内存(索引中每个文档一位)。

如果你要一遍又一遍地使用同一个查询,那么你可能需要付出一次性能/内存命中并让以后的用法更快。 但如果这是一次性查询,那几乎肯定不值得。

(另外,如果要重用它,请使用CachingWrapperFilter以便缓存filter。)

如果filter将被重用,那么由于缓存目的,使用它而不是查询是明智的。 如果您不打算使用评分或字段值,则使用filter而不是查询也是有意义的。

希望这可以帮助。

我在http://wiki.apache.org/lucene-java/ImproveSearchingSpeed中找到了这个,它似乎建议使用filter而不是查询。 直觉上它对我来说更有意义,因为他们几乎应该做同样的事情,唯一的区别是得分中没有使用filter。

考虑使用filter。 使用缓存的位集filter而不是使用查询子句将结果限制到索引的一部分可能更有效。 对于匹配大量索引的大量文档的限制尤其如此。 filter通常用于将结果限制为类别,但在许多情况下可用于替换任何查询子句。 使用Query和Filter之间的一个区别是Query对分数有影响,而Filter没有。