Lucene底层原理和优化经验分享(1)-Lucene简介和索引原理

转自:https://blog.csdn.net/njpjsoftdev/article/details/54015485
 基于Lucene检索引擎我们开发了自己的全文检索系统,承担起后台PB级、万亿条数据记录的检索工作,这里向大家分享下Lucene底层原理研究和一些优化经验。
  从两个方面介绍:
  1. Lucene简介和索引原理
  2. Lucene优化经验总结

  1. Lucene简介和索引原理

      该部分从三方面展开:Lucene简介、索引原理、Lucene索引实现。

1.1 Lucene简介

  Lucene最初由鼎鼎大名Doug Cutting开发,2000年开源,现在也是开源全文检索方案的不二选择,它的特点概述起来就是:全Java实现、开源、高性能、功能完整、易拓展,功能完整体现在对分词的支持、各种查询方式(前缀、模糊、正则等)、打分高亮、列式存储(DocValues)等等。
  而且Lucene虽已发展10余年,但仍保持着一个活跃的开发度,以适应着日益增长的数据分析需求,最新的6.0版本里引入block k-d trees,全面提升了数字类型和地理位置信息的检索性能,另基于Lucene的Solr和ElasticSearch分布式检索分析系统也发展地如火如荼,ElasticSearch也在我们项目中有所应用。
  Lucene整体使用如图所示:
lucene角色

  结合代码说明一下四个步骤:

IndexWriter iw=new IndexWriter();//创建IndexWriter
Document doc=new Document( new StringField(“name”, “Donald Trump”, Field.Store.YES)); //构建索引文档
iw.addDocument(doc); //做索引库
IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(index)));
IndexSearcher searcher = new IndexSearcher(reader); //打开索引
Query query = parser.parse(“name:trump”);//解析查询

TopDocs results =searcher.search(query, 100);//检索并取回前100个文档号
for(ScoreDoc hit:results.hits)
{
Document doc=searcher .doc(hit.doc)//真正取文档
}
1
2
3
4
5
6
7
8
9
10
11
12
  使用起来很简单,但只有知道这背后的原理,才能更好地用好Lucene,后面将介绍通用检索原理和Lucene的实现细节。

1.2 索引原理

  全文检索技术由来已久,绝大多数都基于倒排索引来做,曾经也有过一些其他方案如文件指纹。倒排索引,顾名思义,它相反于一篇文章包含了哪些词,它从词出发,记载了这个词在哪些文档中出现过,由两部分组成——词典和倒排表。

这里写图片描述

  其中词典结构尤为重要,有很多种词典结构,各有各的优缺点,最简单如排序数组,通过二分查找来检索数据,更快的有哈希表,磁盘查找有B树、B+树,但一个能支持TB级数据的倒排索引结构需要在时间和空间上有个平衡,下图列了一些常见词典的优缺点:
这里写图片描述

  其中可用的有:B+树、跳跃表、FST
  B+树:
              mysql的InnoDB B+数结构
这里写图片描述

理论基础:平衡多路查找树
优点:外存索引、可更新
缺点:空间大、速度不够快

1
2
3
4
  跳跃表:
这里写图片描述

优点:结构简单、跳跃间隔、级数可控,Lucene3.0之前使用的也是跳跃表结构,后换成了FST,但跳跃表在Lucene其他地方还有应用如倒排表合并和文档号索引。
缺点:模糊查询支持不好

1
2
3
  FST
  Lucene现在使用的索引结构
这里写图片描述

理论基础: 《Direct construction of minimal acyclic subsequential transducers》,通过输入有序字符串构建最小有向无环图。
优点:内存占用率低,压缩率一般在3倍~20倍之间、模糊查询支持好、查询快
缺点:结构复杂、输入要求有序、更新不易
Lucene里有个FST的实现,从对外接口上看,它跟Map结构很相似,有查找,有迭代:
1
2
3
4
5
String inputs={“abc”,”abd”,”acf”,”acg”}; //keys
long outputs={1,3,5,7}; //values
FST fst=new FST<>();
for(int i=0;i

猜你喜欢

转载自blog.csdn.net/witsmakemen/article/details/80258862