lucene字典实现原理

1 lucene字典

使用lucene进行查询不可避免都会使用到其提供的字典功能,即根据给定的term找到该term所对应的倒排文档id列表等信息。实际上lucene索引文件后缀名为tim和tip的文件实现的就是lucene的字典功能。

怎么实现一个字典呢?我们马上想到排序数组,即term字典是一个已经按字母顺序排序好的数组,数组每一项存放着term和对应的倒排文档id列表。每次载入索引的时候只要将term数组载入内存,通过二分查找即可。这种方法查询时间复杂度为Log(N),N指的是term数目,占用的空间大小是O(N*str(term))。排序数组的缺点是消耗内存,即需要完整存储每一个term,当term数目多达上千万时,占用的内存将不可接受。

2 常用字典数据结构

很多数据结构均能完成字典功能,总结如下。

数据结构 优缺点
排序列表Array/List 使用二分法查找,不平衡
HashMap/TreeMap 性能高,内存消耗大,几乎是原始数据的三倍
Skip List 跳跃表,可快速查找词语,在lucene、redis、Hbase等均有实现。相对于TreeMap等结构,特别适合高并发场景(Skip List介绍
Trie 适合英文词典,如果系统中存在大量字符串且这些字符串基本没有公共前缀,则相应的trie树将非常消耗内存(数据结构之trie树
Double Array Trie 适合做中文词典,内存占用小,很多分词工具均采用此种算法(深入双数组Trie
Ternary Search Tree 三叉树,每一个node有3个节点,兼具省空间和查询快的优点(Ternary Search Tree
Finite State Transducers (FST) 一种有限状态转移机,Lucene 4有开源实现,并大量使用

3 FST原理简析

lucene从4开始大量使用的数据结构是FST(Finite State Transducer)。FST有两个优点:1)空间占用小。通过对词典中单词前缀和后缀的重复利用,压缩了存储空间;2)查询速度快。O(len(str))的查询时间复杂度。

下面简单描述下FST的构造过程(工具演示:http://examples.mikemccandless.com/fst.py?terms=&cmd=Build+it%21)。我们对“cat”、 “deep”、 “do”、 “dog” 、“dogs”这5个单词进行插入构建FST(注:必须已排序)。

1)插入“cat”

插入cat,每个字母形成一条边,其中t边指向终点。

2)插入“deep”

与前一个单词“cat”进行最大前缀匹配,发现没有匹配则直接插入,P边指向终点。

3)插入“do”

与前一个单词“deep”进行最大前缀匹配,发现是d,则在d边后增加新边o,o边指向终点。

4)插入“dog”

与前一个单词“do”进行最大前缀匹配,发现是do,则在o边后增加新边g,g边指向终点。

5)插入“dogs”

与前一个单词“dog”进行最大前缀匹配,发现是dog,则在g后增加新边s,s边指向终点。

最终我们得到了如上一个有向无环图。利用该结构可以很方便的进行查询,如给定一个term “dog”,我们可以通过上述结构很方便的查询存不存在,甚至我们在构建过程中可以将单词与某一数字、单词进行关联,从而实现key-value的映射。

4 FST使用与性能评测

我们可以将FST当做Key-Value数据结构来进行使用,特别在对内存开销要求少的应用场景。Lucene已经为我们提供了开源的FST工具,下面的代码是使用说明。

 1 public static void main(String[] args) {
 2         try {
 3             String inputValues[] = {"cat", "deep", "do", "dog", "dogs"};
 4             long outputValues[] = {5, 7, 17, 18, 21};
 5             PositiveIntOutputs outputs = PositiveIntOutputs.getSingleton(true);
 6             Builder<Long> builder = new Builder<Long>(FST.INPUT_TYPE.BYTE1, outputs);
 7             BytesRef scratchBytes = new BytesRef();
 8             IntsRef scratchInts = new IntsRef();
 9             for (int i = 0; i < inputValues.length; i++) {
10                 scratchBytes.copyChars(inputValues[i]);
11                 builder.add(Util.toIntsRef(scratchBytes, scratchInts), outputValues[i]);
12             }
13             FST<Long> fst = builder.finish();
14             Long value = Util.get(fst, new BytesRef("dog"));
15             System.out.println(value); // 18
16         } catch (Exception e) {
17             ;
18         }
19     }

FST压缩率一般在3倍~20倍之间,相对于TreeMap/HashMap的膨胀3倍,内存节省就有9倍到60倍!(摘自:把自动机用作 Key-Value 存储),那FST在性能方面真的能满足要求吗?下面是在苹果笔记本(i7处理器)进行的简单测试,性能虽不如TreeMap和HashMap,但也算良好,能够满足大部分应用的需求。

参考文献

http://sbp810050504.blog.51cto.com/2799422/1361551

http://blog.sina.com.cn/s/blog_4bec92980101hvdd.html

http://blog.mikemccandless.com/2013/06/build-your-own-finite-state-transducer.html

http://examples.mikemccandless.com/fst.py?terms=mop%2F0%0D%0Amoth%2F1%0D%0Apop%2F2%0D%0Astar%2F3%0D%0Astop%2F4%0D%0Atop%2F5%0D%0Atqqq%2F6&cmd=Build+it%21

时间: 2025-01-02 17:17:28

lucene字典实现原理的相关文章

Lucene全文搜索原理与使用

本文中主要是对于Lucene全文搜索的基础原理进行简单的分析,以及Lucene实现全文搜索的流程,之后就是Lucene在Java中的最简单使用:创建索引,查询索引库: 本文中使用的Lucene主要是4.10.3和6.0.0,两个版本的原理相同,但是API的使用并不相同: 1.结构化数据与非结构化数据 2.非结构化数据搜索 3.全文搜索 4.搜索如何实现 5.Lucene实现全文搜索流程 6.Lucene的API使用 1.结构化数据与非结构化数据 结构化数据:指具有固定格式或有限长度的数据,如数据

搜索引擎基础概念(2)—— 构建单词词典

Lucene单词词典 使用lucene进行查询不可避免都会使用到其提供的单词词典功能,即根据给定的term找到该term所对应的倒排文档id列表等信息.实际上lucene索引文件后缀名为tim和tip的文件实现的就是lucene的单词词典功能. 怎么实现一个单词词典呢?我们马上想到排序数组,即term字典是一个已经按字母顺序排序好的数组,数组每一项存放着term和对应的倒排文档id列表.每次载入索引的时候只要将term数组载入内存,通过二分查找即可.这种方法查询时间复杂度为Log(N),N指的是

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

基于Lucene检索引擎我们开发了自己的全文检索系统,承担起后台PB级.万亿条数据记录的检索工作,这里向大家分享下Lucene底层原理研究和一些优化经验. 从两个方面介绍: 1. Lucene简介和索引原理 2. Lucene优化经验总结 1. Lucene简介和索引原理 该部分从三方面展开:Lucene简介.索引原理.Lucene索引实现. 1.1 Lucene简介 Lucene最初由鼎鼎大名Doug Cutting开发,2000年开源,现在也是开源全文检索方案的不二选择,它的特点概述起来就是

Lucene 4.X 全套教程

http://www.cnblogs.com/forfuture1978/category/300665.html Lucene 4.X 倒排索引原理与实现: (3) Term Dictionary和Index文件 (FST详细解析) 摘要: 我们来看最复杂的部分,就是Term Dictionary和Term Index文件,Term Dictionary文件的后缀名为tim,Term Index文件的后缀名是tip,格式如图所示.Term Dictionary文件首先是一个Header,接下来

万亿级日志与行为数据存储查询技术剖析——Hbase系预聚合方案、Dremel系parquet列存储、预聚合系、Lucene系

转自:http://www.infoq.com/cn/articles/trillion-log-and-data-storage-query-techniques?utm_source=infoq&utm_medium=popular_widget&utm_campaign=popular_content_list&utm_content=homepage 目前大数据存储查询方案大概可以分为:Hbase系.Dremel系.预聚合系.Lucene系,笔者就自身的使用经验说说这几个系

MySQL和Lucene索引对比分析

MySQL和Lucene都可以对数据构建索引并通过索引查询数据,一个是关系型数据库,一个是构建搜索引擎(Solr.ElasticSearch)的核心类库.两者的索引(index)有什么区别呢?以前写过一篇<Solr与MySQL查询性能对比>,只是简单的对比了下查询性能,对于内部原理却没有解释,本文简单分析下两者的索引区别. MySQL索引实现 在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式. M

Lucene建立索引库

问题?Lucene如何建立索引库,lucene所需要的jar包是那些  , lucene如何使用索引库,lucene的核心原理 一.Lucene是什么? 全文检索只是一个概念,而具体实现有很多框架,lucene是其中的一种方式.本文将以lucene3.0进行开发 官兵与Luncne的jar包可以去官网下载:点击打开链接,不过好像Lucene已经更新到6.1了. 二.建立索引库 1.互联网搜索全文搜索引擎结构图: 2.Lucene的结构图: 说明: (1)在数据库中,数据库中的数据文件存储在磁盘上

lucene自定义同义词实现

lucene同义词搜索原理其实是根据 PositionIncrementAttribute 和 CharTermAttribute的次元记录信息来实现的,当前使用lucene版本为4.8.0首先同义词要实现 package lucene_index; import java.io.IOException; import java.util.Map; import java.util.Stack; import org.apache.lucene.analysis.TokenFilter; imp

Lucene.net入门学习(结合盘古分词)

Lucene简介 Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的 查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言).Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中 实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎. Lucene.net简介 Lucene.net是Lucene的.net移植版本,是一个