`
kernaling.wong
  • 浏览: 78873 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Lucene性能优化之使用Lucene预排序加速搜索速度

    博客分类:
  • java
 
阅读更多

                                                                                                             

      简单说搜索个过程,Lucene 在搜索的程序简单分成两部分,搜索与排序。高手请忽略下面我的讲解。

  搜索:

   通过倒排的索引找到对应的 docId 集,拿出来,通过 Collector 类的实现类中的 collect(int docId )

          就可以拿到了。

  排序:

   因为拿出来后,还有一个排序的过程,现在我们只讨论按某一个数字字段进行排序,Collector 的实现类都会从一个叫 FieldCache 类中,加载了需要排序的字段的一个 数组的值,数组下标为docId, 然后通过 FieldValueHitQueue 这一个类进行排序了。

 

  象一般来讲,做搜索应用都会按时间从远到近,一段一段地把数据存入到索引中,完成后,如有新增的数据,只需要把新增那部分存入索引则可,这是很普遍的做法。

  完成后似乎一切很顺利,哦,对了,还有一个事情就是其实很多的业务应用中,都是把搜索结果按一个或者多个字段排序了,比如:把搜索出来的结果,按发布时间倒排,或者按评论数倒排,又或者一个比较常用的业务就是,出报表,把最新的前 1000 条记录按发布时间倒排出来,甚至还要按页数一页一页出来结果。这里暂不讨论按匹配度等排序的情况。

 

  问题的来源:

  因为我们入索引是从远到近的,可以简单地认为,如:发布时间(time)在索引里面都是一种升序的形式存入索引,而搜索出来后排序则是一种倒序的形式,问题就是这样子,按排序算法来说这就是最差的一种情况了,把一个升序排序成倒序,但通过研究Lucene 的索引发现,一旦达到某个数据量,索引里面的并非完全按 时间正序入索引的,而是把document 分成了几段,我想这样子就是为了避免我刚才说的排序最坏的情况出现吧...但只能是治标不治本的做法,仅是折衷的做法。

 

    解决思路:

      现在公司的搜索业务方面的速度不快,估计数据量比较大的原因,整一个集群的速度我个人并不满意。

   在 lucene 的排序中,其实仅仅搜索的速度是挺快的,主要的性能瓶颈在排序那里,然后我深入再发现了解到,公司的搜索业务中很多都使用发布时间倒序完成的,这自然让我产生一种想法,为什么不预先让他们排序好?因为既然是按发布时间倒序完成的,那说明只要命中docId ,则它的排序已经固定下来了。

  1.  在加载索引的时候,通过 termEum 先把某一个时间段排序后,得到一个已经排序好的数组了。

  2.  自己另外再写一个 Collector 的实现类,里面只需要记录命中的 docId,

  3.  完成后,再遍历那个已经排序好的数组,拿出 docId ,看是不是已经命中的,拿够了前 20 条再 break 出来就完成整一个搜索与排序的过程了,

 

  从上面看到,都已经没有排序的过程,因为已经第一步实现了排序。代码我不再演示了,思路已经写在那里了,代码估计对于各路大神也不是什么难事。酷

  下面给出测试的条件与结果:

   索引的结构给一下,只需要留意红框里面的字段就可以了

      

   我分了三次测试条件, 1000万,3000万, 总数,其中 is 字段是为了可以均匀地把数据划分成 10 份。都没有使用分词器,只对数字进行索引。

 

 

        第一次测试

   1000W 数据,按 is 字段,搜索 10 平均得出每一次搜索结果约 300W.按 time 字段倒序,同样条件,对比预排序与lucene 自身排序的速度比较

       

            从结果可以看出,使用预排序的方式后只需要用Lucene 自带排序的 30% 的时间 , 平均每一次搜索结果约 100W 数据,(上面的预排序那里是 44.922 's 我是整理时错误了, sorry .... )

 

 

          第二次测试

   3000W 数据,按 is 字段,搜索 10 平均得出每一次搜索结果约 300W.按 time 字段倒序,同样条件,对比预排序与lucene 自身排序的速度比较

         

           从图上可以看出,同样道理搜索出来的结果,平均每次300W,而且搜索结果数完全一致,排除加载缓存及其他因素,预排序也只需要Lucene 普通排序的 30% 的时间就完成了

 

          第三次测试

         这次比较极端,使用MatchAllQuery 进行排序,就是 1000W 结果参与排序,对于Lucene自带的那种排序方式最致命,而对于预先排序这种方式则是最优的方式。

      

        从上面看到, 1000W 的数据参与排序,Lucene自带的排序方式,用了近 1秒的时间去完成排序,而预排序则只用了 0.3 秒就完成了。

  

 

        总结论:

 

    通过上面的测试,使用预排序的方式,速度提升很明显,为Lucene自带排序的 30 % 时间,对整体的搜索业务性能是一个很大的提升。同时在这里可以扩展一下,通过这样子的预先排序,还可以扩展为,对数字的搜索,或数字区间搜索,而不是使用 NumericQuery ,速度会更快平均在 30ms 的搜索用时,再再再扩展一下,还可以对数字或者数字区间进行统计,比 Solr 的自带的统计速度还要快不少!我稍候还会针对这些做一些扩展开发,请大家稍等。

   缺点: 我觉得,可能是每一次加载索引,或者切换新索引的时间,需要用1分钟左右,进行一个预排序的过程,但我认为相对于优点,这一个缺点不大,一般都是通过加载完新的索引并构造好预排序后,再切换到新索引,问题不大。

   如果对于那些更新并不频繁而数据量特别大如: 半小时更新一次等,我觉得很适合使用这种方法提升性能,而对于那些几分钟就更新一次的搜索业务,我觉得,这种方式就慎用了,毕竟每次这样子预排序一次,对性能伤害很大。

                                                                                          by kernaling.wong@2013.12.30

 

           欢迎转载: http://kernaling-wong.iteye.com/blog/1997365 请注明作者

  • 大小: 106 KB
  • 大小: 150.2 KB
  • 大小: 146.1 KB
  • 大小: 153.4 KB
  • 大小: 143.6 KB
分享到:
评论
2 楼 kernaling.wong 2014-04-30  
fuchao01 写道
你这是用的什么版本的lucene?我的3000w数据,测试起来,比你不预加载还快啊

我用的是 4.5 ,在入索引的时候我是有条件的,索引的时间字段是升序录入的,然后排序是按那个时间倒序的,每天个搜索条件返回给100W ,速度比这还要快?
1 楼 fuchao01 2014-04-28  
你这是用的什么版本的lucene?我的3000w数据,测试起来,比你不预加载还快啊

相关推荐

    用 Lucene 加速 Web 搜索应用程序的开发

    了解如何自定义评分函数以满足特定需求,以及如何通过缓存和优化索引来提高搜索速度。 5. **实时更新与增量索引:** 在Web环境中,数据是动态变化的。学习如何实现实时索引更新,以及如何在不重建整个索引的情况下...

    lucene自定义排序实现

    此外,为了优化性能,你还需要考虑以下几点: - 尽量减少排序字段的类型和数量,因为每增加一个排序字段都会增加索引和查询的复杂性。 - 使用倒排索引(inverted index)来加速字段值的查找,特别是对于大数据量的...

    lucene分组查询优化facet

    在搜索引擎和大数据分析领域,Apache Lucene 是一个广泛使用的全文检索库,它提供了高效、可扩展的搜索功能。其中,Facet(分面)查询是Lucene提供的一种强大的分类和统计功能,它允许用户根据特定的维度(如作者、...

    lucene高级搜索进阶项目_04

    9. **内存缓存**:为了加速搜索,Lucene提供了一种缓存机制,将部分数据存储在内存中,以减少磁盘I/O操作。合理配置缓存策略,可以显著提升搜索性能。 10. **查询优化**:通过查询分析和查询执行优化,如使用...

    lucene全文检索教程

    在性能优化方面,Lucene允许使用缓存(Caching)来加速频繁查询,使用分片(Sharding)来处理大规模数据,以及通过近实时搜索(Near Real-Time Search)来实现在新数据被添加后快速更新索引。 此外,Lucene还支持多...

    最新版windows lucene-8.11.0.zip

    - **性能提升**:新版本可能包含性能优化,如更快的索引和搜索速度,更少的内存占用。 - **API更新**:可能会提供新的API接口或改进现有接口,以便更方便地进行搜索和索引操作。 - **稳定性增强**:修复了前一...

    Lucene学习源码.rar

    Lucene是一个高性能、全文本搜索库,由Apache软件基金会开发,主要用于构建搜索引擎。它提供了一个简单但功能强大的API,使得开发者能够轻松地在应用中实现文本检索功能。Lucene是用Java编写的,但有多种语言的接口...

    基于lucene的ORC 图像搜索源代码

    6. **性能优化**:为了提升搜索速度和内存效率,可能还需要对Lucene的配置进行优化,例如调整分词器、设置缓存、使用近实时搜索等。 在压缩包"Search"中,很可能包含了实现这些功能的源代码,包括ORC的实现、Lucene...

    lucene源码和程序

    同时,这也可以帮助你定制分析器、优化搜索性能,或者扩展Lucene的功能,例如集成到你的Java应用中,构建自定义的搜索引擎。 总之,Lucene是一个强大的全文检索工具,通过其API,开发者可以轻松地在Java应用中实现...

    lucene-4.10.0

    1. 性能提升:4.10.0版本对查询解析、排序和分数计算进行了优化,提高了搜索速度。 2. 查询语法增强:支持更复杂的查询表达式,如短语查询、布尔运算符组合、通配符查询等。 3. 分析器改进:提供更多的预定义分析...

    搜索引擎Lucene_资料

    - **缓存**: 使用缓存机制可以加速常见查询的响应速度。 - **近实时搜索**: Lucene支持近实时搜索,即在添加或更新文档后,几乎立即可被搜索到。 - **倒排索引优化**: 如位图过滤(Bitset Filter)和DocValues,可以...

    lucene-4.6.0官方文档

    例如,合理设置段合并策略可以平衡索引大小和搜索速度。利用Filter和QueryWrapperFilter可以加速查询过滤。 7. **分布式搜索** 对于大型数据集,Lucene支持Solr和Elasticsearch这样的分布式搜索平台,它们在Lucene...

    lucene-4.6.0

    - **性能优化**:4.6.0版本对搜索性能进行了大量优化,包括更快的搜索速度和更少的内存消耗。 - **多字段查询**:支持同时在多个字段上进行查询,提高了查询灵活性。 - **ParellelMergeScheduler**:并行合并策略...

    Lucene3.0做的文件搜索

    为了提高搜索性能,Lucene提供了缓存机制、批量索引、近实时搜索(NRT)等优化手段。缓存可以加速查询响应,批量索引则在大量数据导入时提高效率,NRT技术则允许在索引更新后几乎立即反映出搜索结果。 **7. 其他...

    Lucene.net建立索引,检索分页Demo

    - 倒排索引:Lucene 使用倒排索引来加速搜索,每个词项对应一组包含它的文档编号。 - 索引压缩:通过设置不同的编码策略和压缩级别,可以减小索引占用的空间,提高检索速度。 - 多线程:在多核处理器上,可以使用...

    lucene5.5.0源码

    通过对Lucene 5.5.0源码的深入学习,我们可以理解其内部的工作机制,进一步定制分析器以满足特定语言的搜索需求,或者优化索引和查询性能。此外,还可以探索高级特性,如近实时搜索、多字段排序和 faceted search...

    lucene-2.4.0-src.zip

    Apache Lucene 是一个高性能、全文本搜索引擎库,由Java编写,它为开发者提供了在应用程序中实现全文搜索功能的基本工具。Lucene 2.4.0 版本是这个项目历史上的一个重要里程碑,它包含了丰富的特性和改进。本文将...

    lucene_web项目应用实例

    此外,该项目可能还涉及到了性能优化,如使用NRT(Near Real Time)模式,使得索引更新和查询可以在几乎无延迟的情况下进行。还有可能使用缓存技术来加速重复查询,减少不必要的索引读取。 为了便于调试和测试,...

    lucene:基于Java的全文检索引擎简介

    - **数据结构**:虽然两者都可以看作是一种数据存储结构,但数据库索引主要用于加速特定字段的查找速度,而Lucene的索引则用于全文检索。 - **索引方式**:数据库索引通常是基于树形结构(如B树),而Lucene使用倒排...

Global site tag (gtag.js) - Google Analytics