`
lzj0470
  • 浏览: 1284355 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

lucene开发搜索引擎的一些经验

阅读更多

中文分词:中文分词在建立中文词时有非常大的作用,建立词库就是在中文分词的基础上进行开发的,然后再对词库进行人工的处理才能得到词库。然后我们再用中文词库建立了一批索引,在这个索引上进行一些搜索,对比原来的索引文件进行的搜索,发现用中文分词的索引比标准分词的索引慢,在不加排序的情况下,标准分词的搜索给1秒左右,中文分词就是2秒,加上了排序后标准分词给为2秒,而中文分词则能达5秒左右,差距相当大,观察后发现两个问题,中文分词后的索引文件较标准分词的索引文件大小多出%1左右,经过研究中文分词慢可能是下面的原因,标准分词是将中文分为单个字,中文字单常用的给为5k左右,不常用的共1w,加上英文单词再加上一些其它词等预计标准分词的词条约有2-3w左右,中文分词将不可识别的词按二分法进行拆分,或是拆成单个字,通过对词库的分析发现,经过中文分词的单词光是baizhan论坛就是13万居多,一共有90w个词,再加上其它论坛的分词,预计总共的分词量将是标准分词的几何级数倍,当搜索同一个词时,标准分词只需在2w个词中查找,中文分词需要在可能是上千万的词条中搜索,效率可想而知。

   排序瓶颈,排序是一个非常占用资源的功能,尤其是在数据量特别多的情况下,排序就显示尤为突出,经过测试发现,排序主要和搜索出的数据量有关,比如说搜索出的数据是1w条和1k条的排序是不一样的,但是和索引文件的数据量关系不大,好搜索100m和1G的关系不大,但是搜索1G的也会慢,这是由于搜索数据量有关,而不是排序的关系,因为排序是在搜索完成后再进行的,是对搜索结果进行了一个遍历。Lucene对不同的分词也有不同的效果,经过测试发现lucene用系统自带的标准分词和简单分词搜索的速度较快,使用了中文分词的速度较慢。

   时间范围搜索,使用的是RangeQuery类进行的,测试时没有问题,但用实际数据进行搜索时出现溢出的情况,通过查阅相关资料知道,RangeQuery最大子查询为1024个,可以任意增大,但付出的代价是性能上的损失,增大到10240时也有溢出的现象,进一步发现可以使用语法的方法实现时间段的搜索,字段:[ start TO end ],而且此方法没有溢出,不抛出异常,效快,经过测试发现,时间节省百分之五十,在此要说明的是BooleanQuery有一个setMaxClauseCount函数,用此函数将子查询设置的大些也会减少程序出错的机率,但是付出的就是性能上的降低,如设置为10240时,如果要排序的数据量超过10240个时也将会出现溢出的现象,也以在此建议使用上面说的语法来解决时间段的方式。

   内存索引RAMDirectory,经过测试和资料得到,内存索引搜索的性能提高不大,但是对于建立索引的性能确是非常有帮助,经过测试发现,内存索引在有些时候甚至会比磁盘索引的搜索效率还要慢,但是建立索立大量的索引时确有质的提升,建议建立大量索引时先将索引写入内存索引,当内存索引达到一定量时再将内存索引一次性写入磁盘,但对长时间提供稳定的性能有很大帮助,可以减小硬盘的瓶颈对搜索的影响

   索引的更新,因为lucene不是为频繁进行更新而设计的结构,lucene将所有的精力都放在了如何快速建立索引和进行搜索上,所以数据的更新没有相应的接口,也不可能实再相应的接口,因为它不是像文件一样将数据按条进行存储,它是将数据经过分析后,然后按关键词进行存储,它内部的数据就没有了每条数据的概念,幸好lucene提供了一个删除索引的功能,我们可以利用IndexReader的deleteDocument进行删除索引的操作,它有两个接口可以使用,可以按内部ID号进行删除,也可按词条进行删除,用户可以根据需要进行选择,将要更新的数据先准确删除后再进行添加的操作来完成索引的更新。

   查询类:Query查询有相当多的子类,它分分别实再不同的功能,请查看lucene的官方文档进行研究,其中模糊查询和相似查询相当费时,如果用户想要禁用掉这两个查询可以用如下的代码解决:
   public class XiluQueryParser extends QueryParser
{
 public XiluQueryParser(String f,Analyzer a)
 {
  super(f,a);
 }
 
 /*
  *禁用模糊搜索
  */
 protected Query getFuzzyQuery(String field,
                               String termStr,
                               float minSimilarity)
                        throws ParseException
 {
  throw new ParseException("not allowed");
 }
 
 /*
  *禁止通配符搜索
  */
 protected Query getWildcardQuery(String field,
                                  String termStr)
                           throws ParseException
 {
  throw new ParseException("not allowed");
 }
}
    将QueryParser.parser(title)换为XiluQueryParser.parser(title)即可。

来源:http://club.xilu.com/thinksea/msgview-197162-334.html

分享到:
评论
Global site tag (gtag.js) - Google Analytics