Lucene 性能优化

优化搜索性能
虽然建立索引的操作非常耗时,但是那毕竟只在最初创建时才需要,平时只是少量的维护操作,更何况这些可以放到一个后台进程处理,并不影响用户搜索。我们创建索引的目的就是给用户搜索,所以搜索的性能才是我们最关心的。下面就来探讨一下如何提高搜索性能。

1
将索引放入内存
这是一个最直观的想法,因为内存比磁盘快很多。 Lucene 提供了 RAMDirectory 可以在内存中容纳索引:

Directory fsDir = FSDirectory.getDirectory(“/data/index/”, false);
Directory ramDir = new RAMDirectory(fsDir);
Searcher searcher = new IndexSearcher(ramDir);

但是实践证明 RAMDirectoryFSDirectory 速度差不多,当数据量很小时两者都非常快,当数据量较大时(索引文件 400MRAMDirectory 甚至比 FSDirectory 还要慢一点,这确实让人出乎意料。
而且 lucene 的搜索非常耗内存,即使将 400M 的索引文件载入内存,在运行一段时间后都会 out of memory ,所以个人认为载入内存的作用并不大。

2
优化时间范围限制
既然载入内存并不能提高效率,一定有其它瓶颈,经过测试发现最大的瓶颈居然是时间范围限制,那么我们可以怎样使时间范围限制的代价最小呢?
当需要搜索指定时间范围内的结果时,可以:
1
、用 RangeQuery ,设置范围,但是 RangeQuery 的实现实际上是将时间范围内的时间点展开,组成一个个 BooleanClause 加入到 BooleanQuery 中查询,因此时间范围不可能设置太大,经测试,范围超过一个月就会抛 BooleanQuery.TooManyClauses , 可以通过设置 BooleanQuery.setMaxClauseCount(int maxClauseCount) 扩大,但是扩大也是有限的,并且随着 maxClauseCount 扩大,占用内存也扩大
2
、用 RangeFilter 代替 RangeQuery ,经测试速度不会比 RangeQuery 慢,但是仍然有性能瓶颈,查询的 90% 以上时间 耗费在 RangeFilter ,研究其源码发现 RangeFilter 实际上是首先遍历所有索引,生成一个 BitSet ,标记每个 document ,在时间范围 内的标记为 true ,不在的标记为 false ,然后将结果传递给 Searcher 查找,这是十分耗时的。
3
、进一步提高性能,这个又有两个思路:
a
、缓存 Filter 结果。既然 RangeFilter 的执行是在搜索之前,那么它的输入都是一定的,就是 IndexReader ,而 IndexReader 是由 Directory 决定的,所以可以认为 RangeFilter 的结果是由范围的上下限决定的,也就是由具体的 RangeFilter 对象决定,所以我们只要以 RangeFilter 对象为键,将 filter 结果 BitSet 缓存起来即可。 lucene API 已经提供了一个 CachingWrapperFilter 类封装了 Filter 及其结果,所以具体实施起来我们可以 cache CachingWrapperFilter 对象,需要注意的是,不要被 CachingWrapperFilter 的名字及其说明误 导, CachingWrapperFilter 看起来是有缓存功能,但的缓存是针对同一个 filter 的,也就是在你用同一个 filter 过滤不同 IndexReader 时,它可以帮你缓存不同 IndexReader 的结果,而我们的需求恰恰相反,我们是用不同 filter 过滤同一个 IndexReader ,所以只能把它作为一个封装类。
b
、降低时间精度。研究 Filter 的工作原理可以看出,它每次工作都是遍历整个索引的,所以时间粒度越大,对比越快,搜索时间越短,在不影响功能的情况下,时间精度越低越好,有时甚至牺牲一点精度也值得,当然最好的情况是根本不作时间限制。
下面针对上面的两个思路演示一下优化结果(都采用 800 线程随机关键词随即时间范围):
第一组,时间精度为秒:
方式 直接用 RangeFilter 使用 cache 不用 filter
平均每个线程耗时 10s 1s 300ms

第二组,时间精度为天
方式 直接用 RangeFilter 使用 cache 不用 filter
平均每个线程耗时 900ms 360ms 300ms

由以上数据可以得出结论:
1
、 尽量降低时间精度,将精度由秒换成天带来的性能提高甚至比使用 cache 还好,最好不使用 filter
2
、 在不能降低时间精度的情况下,使用 cache 能带了 10 倍左右的性能提高。

3
使用更好的分析器
这个跟创建索引优化道理差不多,索引文件小了搜索自然会加快。当然这个提高也是有限的。较好的分析器相对于最差的分析器对性能的提升在 20% 以下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值