lucene字典实现原理——FST

更新时间:2023-07-20 04:02:17 阅读: 评论:0

lucene字典实现原理——FST
转⾃:
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、Hba等均有实现。相对于TreeMap等结构,特别适合⾼并发场景()
Trie适合英⽂词典,如果系统中存在⼤量字符串且这些字符串基本没有公共前缀,则相应的trie树将⾮常消耗内存()
Double Array Trie适合做中⽂词典,内存占⽤⼩,很多分词⼯具均采⽤此种算法()
Ternary Search Tree三叉树,每⼀个node有3个节点,兼具省空间和查询快的优点()
Finite State Transducers折叠英语
(FST)⼀种有限状态转移机,Lucene 4有开源实现,并⼤量使⽤
3 FST原理简析
lucene从4开始⼤量使⽤的数据结构是FST(Finite State Transducer)。FST有两个优点:1)空间占
⽤⼩。通过对词典中单词前缀和后缀的重复利⽤,压缩了存储空间;2)查询速度快。O(len(str))的查询时间复杂度。
c罗是哪个国家下⾯简单描述下FST的构造过程(⼯具演⽰:)。我们对“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 = Singleton(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                pyChars(inputValues[i]);献血真实坏处
11                builder.IntsRef(scratchBytes, scratchInts), outputValues[i]);
12            }
13            FST<Long> fst = builder.finish();
14            Long value = (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倍!(摘⾃:),那FST在性能⽅⾯真的能满⾜要求吗?
下⾯是我在苹果笔记本(i7处理器)进⾏的简单测试,性能虽不如TreeMap和HashMap,但也算良好,能够满⾜⼤部分应⽤的需求。参考⽂献

本文发布于:2023-07-20 04:02:17,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1106285.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:内存   数组   查询   字典   前缀   数据结构
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图