在Lucene基本原理(四)和(五)中,介绍了Lucene索引的构成,Lucene 基本原理(三)索引的构成 是基于Lucene2.9.0版本概述索引的组成。倒排索引的核心是“单词字典”和“倒排列表”。从Lucene4.0之后,构成索引的字典的底层数据结构转换为FST(Finite State Transducer)中文,有穷状态转换器。接下来将简单介绍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的映射。

FST以字节的方式存储所有的term Index,这种压缩方式可以有效的缩减存储空间(优点),使得term index足以放进内存,但这种方式也会导致查找时需要更多的CPU资源(缺点,查找性能一般)。

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,但也算良好,能够满足大部分应用的需求。

关于FST的底层原理,详见此论文:https://cs.nyu.edu/~mohri/pub/fla.pdf 。不过,我相信很多人不会看完(^…^)

5.Lucene 基本原理(六)字典实现原理 FST(Finite State Transducer)相关推荐

  1. lucene随笔-FST(Finite State Transducer)有限状态传感器

    lucene版本:6.5.1 有限状态传感器,FST(Finite State Transducer)在lucene中扮演着非常重要的一个角色,在4.0后的版本lucene大量使用了这种数据结构,主要 ...

  2. lucene字典实现原理——FST

    转自:http://www.cnblogs.com/LBSer/p/4119841.html 1 lucene字典 使用lucene进行查询不可避免都会使用到其提供的字典功能,即根据给定的term找到 ...

  3. 字典数据结构-FST(Finite State Transducers)

    http://www.cnblogs.com/LBSer/p/4119841.html 1 lucene字典 使用lucene进行查询不可避免都会使用到其提供的字典功能,即根据给定的term找到该te ...

  4. FST(Finite State Transducers, 有限状态转换器)简介及示例

    一.简介 Finite State Transducers 简称 FST, 中文名:有穷状态转换器.FST目前在语音识别和自然语言搜索.处理等方向被广泛应用. 例如,在自然语言处理中,经常会遇到一些针 ...

  5. 【Elasticsearch】es FST (Finite State Tranduer) 有限状态转换器

    1.概述 FST 有限状态转换器 有一篇博客我有翻译到这篇博客. 参考:[elasticsearch]You AutoComplete Me FST数构建的树如下 演示网站地址:http://exam ...

  6. lucene字典实现原理

    文章转自https://www.cnblogs.com/LBSer/p/4119841.html 1 lucene字典 使用lucene进行查询不可避免都会使用到其提供的字典功能,即根据给定的term ...

  7. python字典实现原理-哈希函数-解决哈希冲突方法

    python字典实现原理-哈希函数-解决哈希冲突方法 参考文章: (1)python字典实现原理-哈希函数-解决哈希冲突方法 (2)https://www.cnblogs.com/guyannanfe ...

  8. lucene基本原理

    1.术语 lucene 在存储它的全文索引结构时,是有层次结构的,这涉及到5个层次:索引(Index):段(Segment):文档(Document):域(Field):词(Term),他们的关系如下 ...

  9. (转)字典树原理+实现

    字典树,高端点就是tire树,或者前缀树,其实就是一个挺简单的算法,但一直没学,昨晚上训练有涉及到,今天来突击一下,发现不是那么难 先插眼一个大牛的博客(因为实在懒得复制粘贴了): https://b ...

  10. 带你自学Python系列(九):一文读懂Python中字典应用原理!

    ↑ 点击上方[计算机视觉联盟]关注我们 今天是小编持续更新关于Python的知识总结以及Python实践项目应用的第9天,带你利用零碎时间自学最受欢迎的编程语言之一Python语言.你和小编一起打卡了 ...

最新文章

  1. [MySQL优化案例]系列 -- 用TIMESTAMP类型取代INT和DATETIME
  2. SpringBoot 2.x 整合Mybatis一:基础
  3. IE6-IE11兼容性问题列表及解决办法
  4. OpenDDS用idl生成自定义数据类型时遇到的一个问题
  5. Java8新特性:Stream介绍和总结
  6. 开源自研新基建,内核实践云数据,当此方为嘉年华 - 2020嘉年华大会侧记
  7. 如何运行从github拉取的vue项目
  8. 2017蓝桥杯结果填空:迷宫
  9. Tomcat如果默认8080被占用修改端口号和查询端口号地址
  10. CentOS7下如何正确安装并启动Docker(图文详解)
  11. 基于SSM的电影购票系统
  12. 魔力服务器修改器,魔力宝贝修改器
  13. Win10家庭版安装VMware虚拟机-开启时出现蓝屏的问题
  14. C#基础之vs2010安装与使用教程
  15. 控制天象,世间的最强者!
  16. 手机二维码~~~ZXing简介
  17. 深入浅出contenteditable富文本编辑器
  18. EasyExcel 批量添加批注
  19. 富人的思维方式(转)
  20. 支持IEC 61850的设备,数据如何能有效的采集管理,如何实现数据可视化?

热门文章

  1. 软件工程第二次作业——git的使用
  2. Visual C# 操作 Excel 文件(二) 封裝成 MyExcel 類
  3. 跨页面的多选功能实现
  4. MetaSploit攻击实例讲解------终端下PostgreSQL数据库的使用(包括kali linux 2016.2(rolling) 和 BT5)...
  5. Linux服务器监控性能测试
  6. Google IO 2018开发者大会:Android P
  7. org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; 文件提前结
  8. 纯前端滑块拼图验证组件(多端兼容)
  9. 公安大数据可视化指挥决策平台
  10. 互联网产品经理的主要职责(产品经理工作职责)