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

时间:2011-06-24 01:19:26

标签: java lucene

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

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

4 个答案:

答案 0 :(得分:12)

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

  

如果你不缓存过滤器,查询会更快,就像ConjunctionScorer一样   在Lucene中有优化,目前不用于过滤器。   过滤器很好,如果你缓存它们(例如,如果你总是有相同的访问权限)   对应用于所有查询的特定用户的限制)。在   在这种情况下,Filter只执行一次并进一步缓存   请求然后与查询结果集相交。

     

如果您只想要例如随机“过滤”,例如通过可变数值范围   就像地理搜索中的边界框一样,使用查询,查询最多   案例更快(例如范围查询和类似的东西 - 称为MultiTermQueries    - 内部也通过相同的BitSet算法实现   过滤 - 实际上它们只是由Scorer-impl包装的过滤器。但是   记分器将查询和您的“过滤器”查询放在一起   (ConjunctionScorer)通常比应用的代码更快   搜索后过滤。这可能会有一些改进,但总的来说   过滤器是Lucene中不再需要的东西,所以那里   已经有一些方法可以使过滤器和查询相同,并且   而是能够缓存非评分查询。这会很多   代码更容易。

     

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

     

乌韦

答案 1 :(得分:8)

与Dennis的回答相反:不,你可能不想使用过滤器,除非你要多次重复使用同一个查询。

NumericRangeFilter只是MultiTermQueryWrapperFilter的子类,这意味着它实际上是这样的:

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

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

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

如果您要反复使用相同的查询,那么支付性能/内存命中一次并让以后的用法更快可能是值得的。但如果这是一次性查询,那几乎肯定不值得。

(另外,如果您要重复使用它,请使用CachingWrapperFilter以便缓存过滤器。)

答案 2 :(得分:1)

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

希望这会有所帮助。

答案 3 :(得分:1)

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

  

考虑使用过滤器。限制可能更有效   使用缓存的位集过滤器得到索引的一部分   而不是使用查询子句。对于限制尤其如此   匹配大量索引的大量文档。过滤器是   通常用于将结果限制为一个类别,但可以在很多   case用于替换任何查询子句。一个区别   使用Query和Filter是Query对其产生影响   过滤器没有得分。