FST是lucene中用来存储字典,并进行检索的核心数据结构,我记得在lucene3.0版本前都用的是跳跃链表(不清楚的同学以后我会专门写一篇磁盘索引技术来说清楚,网上也有相关资料),实际上采用该数据结构的最大的好处是比跳跃链表更加节省存储空间,它的速度与跳跃链表相比如何具体没测过(但从理论上分析,fst本质上是个图结构,当查询一个词典时需要对图中节点进行解析,其中有大量的位运算并按路径进行搜索比较耗费cpu,而跳跃链表没那么多位运算但是需要遍历小区间的每个词典进行匹配,所以各有优势),但可以肯定的是它比hashmap慢。其实跳跃链表索引技术在当前最新的lucene版本7.6中的DocValues特性中仍然使用具体请参考谈谈lucene的DocValues特性之SortedDocValuesField,不知是否可以认为跳跃链表会比FST速度更快?

FST本质上是一个比HashMap有更强大功能keyvalue存储结构,它的概念视图可以访问“http://examples.mikemccandless.com/fst.py?terms=pop%2Fabe%0D%0Astar%2Fabc%0D%0Asto%2Facs%0D%0Astop%2Fabd%0D%0Asuop%2Fcvb%0D%0A%0D%0A%0D%0A&cmd=Build+it%21”该网站看到。注意:在生成FST时,词典必须按key进行排序(原因在于排序后能生成一个最小化的DFA),它是共享前缀和后缀的,实际上前缀树就是它的一个简化版。

以下对照FST截图说明节点与边的关键属性:

说明:红线代表该节点的最后一个路径,加粗的线代表该路径指向结束节点,value会通过提取公共前缀然后存储在线上(有种特殊情况会将值存储在节点上如sto/acs与stop/abd,但是lucene在序列化的时候会将值存储在线上的nextFinalOut属性中),从开始节点到结束节点的每一个路径代表每个key/value对,在查找一个key时,通过对路径节点上的边进行二分查找就可以快速进行定位。当然当一个节点的边太多的时候lucene还会进一步优化,是否共享后缀也是可配置的,当不共享后缀并且没有value时就是一个典型的前缀树。大家应该了解到双数组trie是对前缀树的一种优化,实际上FST又何尝不是呢!

理解FST并不难,难点在于一个高效的实现,以下是对lucene源码实现的关键性分析,具体细节还请看源码:

1、对于节点node而言分为序列化的node与未序列化的node,未序列化的node是可以不断复用的(当将节点序列化后,node会被重置),每次插入一个key时,首先查找与上一个key的公共前缀,然后将上个key的第lastkey.length个节点到第prefixLen+1个节点开始序列化(由于经过排序后这些节点以后也不会发生变化因此可以序列化);

2、当序列化完成后会对value值通过查找公共前缀进行进一步压缩处理,从第2个节点开始一直处理到第prefixLen个节点。实现时将当前值与上一个值的公共前缀设置给当前节点的父节点,将剩余的后缀推送到当前节点的每个边上(当遇到终止节点时,会将后缀保存在节点上一份),然后将当前值与公共前缀的后缀设置为当前值继续该循环;

3、根节点总是在最后进行序列化。

4、在对节点序列化时会将每条边依次写入一个类似于ByteBlockPool这样的逻辑字节流中(其意义可参考谈谈lucene中的BytesRefHash),首先会写入元数据(就是上面提到的边的属性),然后写入边上对应的lab,再写入value,最后写入指向节点的地址。注意:这里不考虑当一个节点的边太多的时候所做的优化,写完之后需要将字节序列进行反转,然后从后向前进行读取。

fst 共享后缀_谈谈lucene中的FST相关推荐

  1. fst 共享后缀_关于Lucene的词典FST深入剖析

    核心是在于如何快速的依据 查询词 快速的查找到所有的相关文档,这也是 倒排索引(Inverted Index) 的核心思想.那么如何设计一个快速的(常量,或者1)定位词典的数据结构就显得尤其重要.简单 ...

  2. fst 共享后缀_FST源代码解读2——FST的生成

    本篇博客介绍FST的生成.它使用的是生成器模式,因为FST的生成太复杂了,所以必须使用生成器模式,他的类是:org.apache.lucene.util.fst.Builder.Builder(INP ...

  3. fst 共享后缀_FST源代码解读1——FST是什么

    在之前研究IK的时候,看了他存储词典的格式,接触到了前缀树这种数据结构,他的好处是可以共享前缀,但是并不能共享后缀,而FST就能共享后缀,实现更加高效的存储或者查找.当然FST比前缀树添加了一个要求: ...

  4. python中遍历是什么意思_谈谈python中的遍历

    标签: 谈谈python中的遍历 python中也有像java中的for...each....在python中是for...in... 其实感觉差不多,不过python的规则更灵活一点, 只要是可以进 ...

  5. 反arp攻击软件_谈谈电子欺骗中的ARP欺骗

    ARP欺骗是一种非常古老的电子欺骗攻击,虽然从诞生到现在已经过去了二十多年,但在很多网络中仍然有效.之前写的 沈传宁:谈谈TCP/IP协议的学习​zhuanlan.zhihu.com 文章中也提到,我 ...

  6. this调用语句必须是构造函数中的第一个可执行语句_谈谈JavaScript中的函数构造式和new关键字...

    您是否曾困惑于 Javascript 中的new关键字呢?是否曾想理解关于 function 和 constructor 的区别是什么呢? 大多数 Javascript 的新开发者不太想要使用new关 ...

  7. pythonwhile语句是什么意思_谈谈Python中的while循环语句

    前言 python中有两种循环,while和for,两种循环的区别是,while循环之前,先判断一次,如果满足条件的话,再循环,for循环的时候必须有一个可迭代的对象,才能循环,比如说得有一个数组. ...

  8. 局域网arp攻击_谈谈电子欺骗中的ARP欺骗

    ARP欺骗是一种非常古老的电子欺骗攻击,虽然从诞生到现在已经过去了二十多年,但在很多网络中仍然有效.之前写的 沈传宁:谈谈TCP/IP协议的学习​zhuanlan.zhihu.com 文章中也提到,我 ...

  9. mysql基数是什么意思_谈谈MySQL中的基数是啥?

    1基数是啥? 大白话讲:基数指的就是MySQL表中某一列的不同值的数量. 如果这一列是唯一索引,那基数 == 行数. 如果这一列是sex,枚举类型只有男女,那它是基数就是2.Cardinality越高 ...

最新文章

  1. 线上学python哪家好-Python线下培训好还是线上培训好
  2. 【运筹学】线性规划 人工变量法 ( 人工变量法案例 | 第二次迭代 | 中心元变换 | 检验数计算 | 最优解判定 | 选择入基变量 | 选择出基变量 )
  3. surefire 拉起testng单元测试类的源码流程阅读(二)
  4. 自定义控件详解(四):Paint 画笔路径效果
  5. 据说网易搜索引擎-超越GOOGLE
  6. 我的世界java版复仇双持_我的世界1.9更新之双持武器
  7. 8.11 NOIP模拟测试17 入阵曲+将军令+星空
  8. 领域驱动设计 软件核心复杂性应对之道_DDD - 领域驱动设计对软件复杂度的应对(上)...
  9. 【20161108】总结
  10. 【人脸识别】基于matlab ksvd字典学习人脸表情识别【含Matlab源码 460期】
  11. VS2013 下载地址
  12. react后台管理项目
  13. 计算机多媒体设备维护维修,学校多媒体教学设备的故障检修
  14. 蒙特卡洛算法及简单应用
  15. 教师使用计算机的注意事项,李磊老师:计算机专业考研报考注意事项
  16. TextBlob简介
  17. python白名单验证是什么意思_luminati python+selenium使用方式(白名单和账号密码验证方式)...
  18. GreenDao3.0 使用(包括导入,具体方法,基本使用,加密,数据库升级等)
  19. 通信工程相近专业及工程类专业说明
  20. k8s_node节点得pod频繁重启排查原因

热门文章

  1. 学习方法十二利用自由时间
  2. 体检管理系统——图形报表ECharts
  3. 计算机毕业设计ssm力高灯饰线上交易平台4d59n (1)系统+程序+源码+lw+远程部署
  4. 【转载】2016年上半年中国电商九大总结
  5. 远程登陆mysql服务器命令_mysql 远程登录及常用命令
  6. Pick定理(一个计算点阵中顶点在格点上的多边形面积公式)
  7. PTA-山科-Java(软工)实验(7-10)
  8. 【OpenCV-Python】Contours
  9. Google 社招 | 谷歌云最大规模招聘 就是现在!
  10. java读取修改文件内容_Java对本地文件内容读取、修改、删除的操作