优化搜索性能
虽然建立索引的操作非常耗时,但是那毕竟只在最初创建时才需要,平时只是少量的维护操作,更何况这些可以放到一个后台进程处理,并不影响用户搜索。我们创建索引的目的就是给用户搜索,所以搜索的性能才是我们最关心的。下面就来探讨一下如何提高搜索性能。
1
将索引放入内存
这是一个最直观的想法,因为内存比磁盘快很多。
Lucene
提供了
RAMDirectory
可以在内存中容纳索引:
Directory fsDir = FSDirectory.getDirectory(“/data/index/”, false);
Directory ramDir = new RAMDirectory(fsDir);
Searcher searcher = new IndexSearcher(ramDir);
但是实践证明
RAMDirectory
和
FSDirectory
速度差不多,当数据量很小时两者都非常快,当数据量较大时(索引文件
400M
)
RAMDirectory
甚至比
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%
以下。
- 大小: 198.8 KB
分享到:
相关推荐
Lucene性能优化 #### 3.1 分片与分布式 在大数据量场景下,可以采用分片策略,将索引分散到多个节点上,利用Lucene的分布式搜索能力,提高查询效率。 #### 3.2 延迟索引更新 为了减少实时索引更新对系统性能的...
Lucene 性能优化** 为了提高性能,可以考虑以下方面: - 使用内存缓存提高查询速度。 - 选择合适的分词器,根据语言特性进行优化。 - 使用倒排索引加速查询。 - 调整索引和搜索的内存设置。 - 对大型数据集,可以...
在搜索引擎和大数据分析领域,Apache Lucene 是一个广泛使用的全文检索库,它提供了高效、可扩展的搜索功能。其中,Facet(分面)查询是Lucene提供的一种...理解其原理,掌握优化技巧,是提升Lucene应用性能的关键。
5. Lucene性能优化:探讨缓存策略、索引碎片整理、近实时搜索等技术,以提升系统性能。 通过对Lucene源码的学习,开发者不仅可以掌握全文检索的基本原理,还能深入了解其内部实现,为开发高效、定制化的搜索引擎...
本教程主要探讨的是如何利用Lucene进行索引优化,特别是通过多线程和处理多个目录来提高索引创建效率。 首先,我们需要理解Lucene的索引原理。Lucene将文档分解为词项(tokens),并对每个词项创建倒排索引。倒排...
保持Lucene版本的更新可以确保利用所有可能的性能优化措施。 #### 采用本地文件系统 远程文件系统通常比本地文件系统慢,尤其是在索引构建过程中。若索引必须存储在远程文件系统上,一个有效的策略是在本地文件系统...
Lucene 的优化是指对搜索引擎的性能进行优化。 Lucene 提供了多种优化方式,包括索引优化和搜索优化。 例如,下面的代码演示如何使用 Lucene 对索引进行优化: ```csharp IndexWriter writer = new IndexWriter...
《依赖Lucene的电话号码查询优化》 在信息爆炸的时代,数据检索的效率与准确性成为了决定用户体验的关键因素。本文将深入探讨如何利用Apache Lucene这一强大的全文搜索引擎库,对电话号码查询进行优化,以提高查询...
5. **性能优化** 为了提升搜索效率,Lucene提供了一些优化策略,如缓存、位图过滤、近似搜索等。通过合理配置和调优,可以显著提高系统性能。 6. **Lucene 3.30版本** Lucene 3.30是该库的一个较早版本,它可能...
标题与描述概述的知识点主要集中在Lucene的高亮显示功能,尤其是在处理中文分词时的性能优化策略。以下是对这些知识点的详细展开: ### Lucene的高亮显示 Lucene是一款高性能、全功能的文本搜索引擎库,其高亮显示...
- **性能优化**:对索引和搜索性能进行了进一步优化,提升了处理大量数据时的速度。 - **内存管理**:改进了内存使用策略,降低了内存占用,减少了垃圾收集的影响。 - **查询解析**:增强了查询解析器,支持更复杂...
10. **性能调优**:通过分析源码,开发者可以了解到如何调整各种参数,如缓存大小、合并策略等,来优化Lucene的性能。 总的来说,深入学习Lucene 3.5.0的源码,可以帮助开发者掌握全文检索的核心技术,了解其内部...
本篇文章将深入探讨Lucene的高级应用,结合提供的两个文档《lucene的优化2.doc》和《lucene的优化1.doc》,我们将探讨Lucene的索引优化、查询优化以及一些高级特性的应用。 一、索引优化 1. 多字段索引:Lucene...
《教你运用Lucene算法》 Lucene是一款强大的全文搜索引擎库,它提供了丰富的信息检索功能,包括文本分析、索引构建、搜索以及结果...对于开发者来说,深入理解这些算法有助于优化索引和搜索性能,提升系统的整体效率。
《Apache Lucene核心技术详解:从2.9.4到3.4.0的演变》 Apache Lucene,作为开源的全文检索库,是Java...随着版本的迭代,Lucene不仅提供了更多的功能,也在性能和稳定性上不断优化,为信息检索领域提供了强大的支持。