lucene的高效数据查询
lucene是一个常用的并发处理时的全局搜索引擎,它和目前搜索引擎采取的处理大量查询数据的思路都是,事先把跟关键词相匹配数据存储起来,查找的时候直接把存储好的数据进行返回。
lucene也对内部的数据结构和算法进行优化,著名的有内嵌FST数据结构,在索引生成方面的应用。LZ4的实时压缩算法。
lucene对基本数据结构压缩优化
- 普通的 Int 和 Long 存储一个整数,必须用 32 位和 64 位,哪怕该整数的值为 1 。这样 就带来了存储空间的浪费。
首先lucene在进行存储时,文档id,词频等一定是非负整数。
Vint: 由不超过 4 个 Byte 组成,Byte 的最高位表示是否需要再读取一个 Byte,剩下的 7 位存 储数值。这样当数值范围在[0,127]之间用一个 Byte 就够了,数值范围在[128, 16383]之间用 两个 Byte 就够了,有效节约了存储空间。
VLong: 由不超过 8 个 Byte 组成,存储方式与 VInt 相同。
String: 存储一个 VInt 表示字符串的长度,然后用 UTF8 编码存储字符串。
- Zigzag 编码主要在于对负数的压缩,比如-1(1111 1111 1111 1111 1111 1111 1111 1111), 经过转码后,变成了 1(0000 0000 0000 0000 0000 0000 0000 0001),节约了很多符号位。
- Lucene 中用到的一项技术就是位压缩(bit-packing).这意味着整型数组的类型从固定大小 (8,16,32,64 位)4 种类型,扩展到了[1-64]位共 64 种类型。这样的话,在lucene中的整型数组实际上变为了变长。
FST数据结构
FST本质上是一种有限状态自动机。FST在 Lucene 中的应用多以 FST<Key,Value>的形式出现,其功能与 Map 类似,支持用 Key 来查询 Value;同时 FST 也支持用 Value 来查找最优 Key,这是 Map 做不到的。
其复杂度为O(len(key)),空间利用率高,普通有状态机,如 Trie 树就已经能够实现 O(len(Key))的时间复杂度,然而空间利用率却 低得可怜。
FST 正 是一个最小的、有向的、无环的最小自动机。
但是FST方法有一个局限条件:为了保证最小自动机,给定的 List 必须是有序的。
假设有{w1,w2....,wn} n 个有序的字符串集。 a、先构造一个除 w1 外,最小的 FST。(此时 FST 中有 w1 一个字符串) b、构造一个除 w2 外,最小的 FST。(此时 FST 中有 w1,w2 两个字符串) c、构造一个除 w3 外,最小的 FST。(此时 FST 中有 w1,w2,w3 三个字符串)其实就是一种迭代的思想,通过对字符串后缀和前缀的重复利用以实现状态的压缩, 这也是为什么需要一个排序的 List。
FST实现类map查询
首先我们来看看常用的map字典效率
数据结构 |
优缺点 |
---|---|
排序列表Array/List |
使用二分法查找,不平衡 |
HashMap/TreeMap |
性能高,内存消耗大,几乎是原始数据的三倍 |
Skip List |
跳跃表,可快速查找词语,相对于TreeMap等结构,特别适合高并发场景 |
Trie树 |
适合英文词典,如果系统中存在大量字符串基本没有公共前缀,则相应的trie树将非常消耗内存 |
public static void main(String[] args) throws IOException {
String inputValues[] = {"cat","deep","do","dog","dogs"};
Long outputValues[] = {5L,7L,17L,18L,21L};
//lucene中的int输出
PositiveIntOutputs outputs = PositiveIntOutputs.getSingleton();
//构建FST,并配置输入类型,按byte优化数据存储大小,以及数据的输出类型
Builder<Long> builder = new Builder<Long>(FST.INPUT_TYPE.BYTE1,outputs);
IntsRefBuilder scratchInts = new IntsRefBuilder();
for (int i = 0; i < inputValues.length; i++) {
BytesRef scratchBytes = new BytesRef(inputValues[i].getBytes());
scratchInts.copyUTF8Bytes(scratchBytes);
//build添加的key只能为int
builder.add(scratchInts.toIntsRef(),outputValues[i]);
}
FST<Long> fst = builder.finish();
Long value = Util.get(fst, new BytesRef("dog"));
System.out.println(value); // 18
}
FST压缩率一般在3倍~20倍之间,相对于TreeMap/HashMap的膨胀3倍,内存节省就有9倍到60倍!
我们看到input是经过排序的,也就是ordered。否则生成的就不是最小的FST。另外如果NO_OUTPUT就退化为FSA了,不用执行第4步重新分配output了。
其中freezeTail 方法就是将不再变化的部分进行冰冻,又叫compile,把UnCompileNode,给构建进FST里。进入到FST是先进行compileNode, 然后addNode进去的。
总结以下,加入节点过程:
1)新插入input放入frontier,这里还没有加入FST 2)依据当前input, 对上次插入数据进行freezeTail操作, 放入FST内 3)构建input的转移(Arc)关系 4)解决Output冲突,重新分配output,保证路径统一(NO_OUTPUT,不执行) 最后在finish方法里,执行freezeTail(0), 把所有的input构建进FST内。
FST,不但能共享前缀还能共享后缀。不但能判断查找的key是否存在,还能给出响应的输入output。 它在时间复杂度和空间复杂度上都做了最大程度的优化,使得Lucene能够将Term Dictionary完全加载到内存,快速的定位Term找到响应的output(posting倒排列表)。
- 分布式系统组件之配置中心
- github 提交报403 forbidden的错误解决
- Apache thrift - 使用,内部实现及构建一个可扩展的RPC框架
- redis主从集群搭建及容灾部署(哨兵sentinel)
- 浅谈ASP.NET的Postback
- redis配置详解(中英文)
- 我所理解的Remoting(1):Marshaling & Activation[下篇]
- 5分钟短视频,带你走进日志易SPL,助你日志分析更容易
- Unity Application Block 1.2 for Silverlight - December 2008
- 算法学堂 - 二分查找及其变形
- Zookeeper权限管理与Quota管理
- 刘鹏:保大还是保小?无人汽车也将面临这样的道德窘境
- 浅谈DNS
- silverlight寻奇 - Graphite
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python最简单的图片爬虫,20行代码带你爬遍整个网站
- 用Python把人物头像动漫化,不同的表情给你不同的惊喜
- python苦短-爬取音乐
- python苦短-灵笼说啥
- python爬虫-八佰词云
- python爬虫-beautifulsoup使用
- 深度学习-卷积神经网络原理
- 深度理论VGG-NET 网络
- 只要30行代码!7步教会你Python爬取网页抖音热门视频
- python苦短-CV2
- python实现语音在线合成,让你的小说自己念给你听
- Python爬虫实战:模拟登录淘宝网站
- Python制作动态二维码(附源码,复制再贴修改路径名字即可)
- 新手小白的福利,零基础也能上手的项目——学生信息管理系统
- Python制作小脚本,一键可以让你同事的电脑在你指定时间关机