FieldSelector
提高Lucene检索性能的方法有很多种,这里简单介绍一种常用且便捷可行的方法快速提高Lucene检索性能。在早期的Lucene版本中,使用FieldSelector来决定哪些Fields应该被加载,并以何种方式加载,但是在LUCENE-3309中该接口被废弃,并且提出了新的替代接口StoredFieldVisitor。
FieldCache
另一种提高检索性能的方案是使用FieldCache来缓存Lucene的term values信息,不过该接口目前已被移至org.apache.lucene.uninverting
包下,并且访问权限变成包级私有,也就是说,用户再也无法直接使用FieldCache了,该接口以后仅限于Lucene内部使用。FieldCache的主要作用是缓存用来排序field的值,Lucene会将需要排序的字段都读到内存中进行排序,所占内存大小和文档数量相关。其替代方案是使用DocValues类。其实深入一步,当你的Document只有一个Token的时候,FieldCache还可以被用来快速获取每个Document的field值,因为Lucene只做了反向索引,这种Document->field正向索引是极其耗时的,而FieldCache正好能解决这个问题。
由于这两个接口基本相当于被废弃,这里不再赘述,主要讲解目前实用的StoredFieldVisitor方案。
StoredFieldVisitor
StoredFieldVisitor是一个抽象类,它有一个唯一对外暴露的实现类DocumentStoredFieldVisitor,查看该实现类的Doc文档说明,可知其作用是支持加载所有的stored fields,或者通过Set集合指定请求的fields。
查看DocumentStoredFieldVisitor构造函数
|
|
一个无参构造函数,一个接收Set参数的构造函数,还有一个接收可变参数的构造函数,而可变参数的构造函数中其实就是把可变参数加入Set集合,所以其原理和接收Set集合的构造函数是一样的。
讲了这么多,那么DocumentStoredFieldVisitor的使用场景是什么呢?当用户需要访问各个文档中的某个field的值时,使用IndexSearcher.doc(int docID)可以获得Document,然后再从Document中获得某个域值,当一个Document中field非常多的时候,这种访问速度比较慢,而且只能获得Stored域的值。这时候使用DocumentStoredFieldVisitor可以极大地提高访问速度。下面写个简单的测试代码来看看其性能差距。
|
|
在索引1000000个文档之后,每个文档添加14个不同类型的Field,分别运行Worker1和Worker2,进行十次的基于ID的范围查询,取十次结果的平均值,得到使用DocumentStoredFieldVisitor平均单次耗时6507 ms,不使用DocumentStoredFieldVisitor平均单次耗时8024 ms。可见性能提升还是很可观的,当然该测试并不权威,但是可以给出一个简单直观的比较。