玩ElasticSearch或Solr的童鞋,对于DocValues这个词,时常出现高阶应用开发者的口中。它像一个熟悉的陌生人一样,很多人对于实现排序,分组和一些聚合类操作的需求信手拈来,但对它底层原理却了解不多。

DocValues在LUCENE-3518才引入新特征,初生在Lucene4.0,由Mike(Michael McCandless)提出的。从此Lucene牛逼轰轰了。

1. 为什么要用DocValues ?

假如我们需要对一些数据做一些聚合操作,比如排序,分组该如何实现呢?

基于lucene的solr和es都是使用经典的倒排索引模式来达到快速检索的目的,简单的说就是建立 搜索词=》 文档id列表 这样的关系映射, 然后在搜索时,通过类似hash算法,来快速定位到一个搜索关键词,然后读取其的文档id集合,这就是倒排索引的核心思想,这样搜索数据是非常高效快速的。当然它也是有缺陷的,要实现上面的需求,lucene内部会遍历提取所有出现在文档集合 
的排序字段然后再次构建一个最终的排好序的文档集合list,这个步骤的过程全部维持在内存中操作,而且如果排序数据量巨大的话,非常容易就造成ES内存溢出和性能缓慢

基于这个原因,在lucene4.x之后出现了docvalue这个新特性,在构建索引时会对开启docvalues的字段,在构建索引时会对开启docvalues的字段,额外构建一个已经排好序的文档到字段级别的一个列式存储映射。它带来的好处是:

  • 节省内存
  • 对排序,分组和一些聚合操作时能够大大提升性能

2. 什么时候用DocValues?

通过上面的剖析,总结起来主要以下几个方面:

  • 需要聚合的字段,包括sort,agg,group,facet等
  • 需要提供函数查询的字段
  • 需要高亮的字段,这个确实能加速,但是散仙并不建议把高亮放在服务端程序做
  • 需要参与自定义评分的字段,这个稍复杂,大多数人的场景中,不一定能用到

3. DocValues存储结构

DocValues字段是一个面向列存储的字段,所谓面向列存储,相信大家都不会陌生了,市场上也有好多成熟的列存储框架诸如:Parquet、ORC等。

  • 一个Segment只有一个DocValues
  • 被DocValues标记的字段在建索引时会额外存储文件到值的映射关系
  • 一个DocValues会生成两个文件(dvd,dvm)。dvd,存储这个映射的文件叫DocValues data。dvm,对应的元数据文件叫DocValues Metadata,这里metadata相当于Index文件,用来存储数据的索引,也就是存储数据文件每条记录起始位置以及记录的长度,同时存储数据文件的数据格式等信息(即是元信息)
  • 所有Doc Values存于内存中(堆外内存),这样就可以有超快的访问速度

Doc values通过逆置term和doc间的关系来前面提到的数据聚合的问题。当数据被逆置之后,想要收集到 Doc_1 和 Doc_2 的唯一 token 会非常容易。获得每个文档行,获取所有的词项,然后求两个集合的并集。

Doc      Terms
-----------------------------------------------------------------
Doc_1 | brown, dog, fox, jumped, lazy, over, quick, the
Doc_2 | brown, dogs, foxes, in, lazy, leap, over, quick, summer
Doc_3 | dog, dogs, fox, jumped, over, quick, the
-----------------------------------------------------------------

它也不是实时(同index一样),Writer只负责把DocValues字段按对应DocValues类型写入到内存上,最后在Segment refresh的时候,由Consumer把Writer的内容写入磁盘。

4. DocValues的种类

Lucene提供这五种类型的Writer(DocValues类型),它适配情况是这样的

NONE   不开启docvalue时的状态 
Numeric NumericDocValuesWriter 对于一般的integer/long/float/double/date
Binary BinayDocValuesWriter 对应BinaryField,并且它会被转成byte[]进行存储
Sorted SortedDocValuesWriter 对应String
Sorted Set SortedSetDocValuesWriter 对应StrField字段,但仅限于multiValue="true"的情况
Sorted Number SortedNumericDocValuesWriter 对应所有Trie*Field,包括TrieIntField和TrieDateField

注意:analyzed String字段存储docvalue是没有意义的(因为分词后会生成很多token使得Doc Values效率降低),因此docValues不支持TextField类型

5. docValuesFormat

docValues提供了四种Format,你可能会认为MemoryDocValuesFormat只会存储在内存,而不存储在磁盘,其实真不是这样的。不管是DirectDocValuesFormat还是MemoryDocValuesFormat都会存盘,后缀名分别为.dvdd.dvdm以及.mdvd.mdvm

  • Lucene54DocValuesFormat,默认的Format,存储在磁盘。跟FieldCache比较像,需要时如果没有就去磁盘里读取,不用时也能释放
  • MemoryDocValuesFormat,它绝对不是如名那些In-Memory,它其实还比较复杂。应该说,它允许你只读一定大小的DocValues驻在内存。同时它支持以FST的格式存储。
  • DirectDocValuesFormat,这个关系是Direct,直接。直接存储到磁盘;直接读取出来放在内存。以一个非常简单的结构存储在内存中——数组。它跟MemoryDocValuesFormat最大的一样就是它支持1或0,要么都存;要么都不存
  • SimpleText,Lucene4.0的试验产品

6. 如何使用

//数值存储例子
FieldType num=new FieldType();
num.setStored(true);//设置存储
num.setIndexOptions(IndexOptions.DOCS);//设置索引类型
num.setNumericType(NumericType.DOUBLE);//数值类型
num.setDocValuesType(DocValuesType.NUMERIC);//DocValue类型
Document doc=new Document();
//添加string字段
doc.add(new SortedDocValuesField("id",new BytesRef("01011")));
//添加数值类型的字段  Float,Doule需要额外转成bit位才能存储,Interger和Long则不需要
doc.add(new DoubleField("price", Double.doubleToRawLongBits(25.258), num)); //读取索引文件
DirectoryReader reader=DirectoryReader.open(FSDirectory.open(Paths.get(indexDir)));
//如果有多个段需要merge成一个,获取第一个进行测试,本例中仅仅就有一个段
SortedDocValues str = DocValues.getSorted(reader.leaves().get(0).reader(), "id");
//数值类型
NumericDocValues db = DocValues.getNumeric(reader.leaves().get(0).reader(), "price");
//读取字符串类型的ByteRef然后打印其内容
System.out.println("id:"+str.get(0).utf8ToString());
//注意此处,要与类型对应,如果是Float,则需要Float.intBitsToFloat((int)db.get(0))进行位数还原
System.out.println("price: "+Double.longBitsToDouble(db.get(0)));
reader.close();

在Solr中docvalue默认是全部关闭,比较严谨,大家可酌情开启。在ElasticSearch中,默认docvalue全部激活,比较简单暴力,大家可酌情关闭一些不需要使用docvalue的字段,以节省磁盘空间 。

Lucene系列:番外篇-DocValues相关推荐

  1. 骨龄预测系列---番外篇

    索引 前言 一.DataGenerator是什么? 二.使用步骤 总结 前言 在跑这个系列的代码的时候,发现数据太大了,9G呢~~~,所以引入数据生成器来减轻一下负担 一.DataGenerator是 ...

  2. 【功能安全(ISO 26262)系列】番外篇 第一话 戏说汽车安全是个什么鬼

    更多汽车专业精彩内容尽在微信公众号: AUTO世代 写在前面的话 最近开了个汽车功能安全专题系列: 功能安全(ISO 26262)系列 主要阐述汽车功能安全(ISO 26262)关键专业内容及个人学习 ...

  3. python爬虫进程和线程_python爬虫番外篇(一)进程,线程的初步了解-阿里云开发者社区...

    整理这番外篇的原因是希望能够让爬虫的朋友更加理解这块内容,因为爬虫爬取数据可能很简单,但是如何高效持久的爬,利用进程,线程,以及异步IO,其实很多人和我一样,故整理此系列番外篇 一.进程 程序并不能单 ...

  4. [zt]数学之美番外篇:平凡而又神奇的贝叶斯方法

    数学之美番外篇:平凡而又神奇的贝叶斯方法 Tags: 数学, 机器学习与人工智能, 计算机科学 save it69 saved tags: 贝叶斯 math bayesian algorithm 数学 ...

  5. 转:数学之美番外篇:平凡而又神奇的贝叶斯方法 收藏

    为什么80%的码农都做不了架构师?>>>    转自:http://blog.csdn.net/pongba/archive/2008/09/21/2958094.aspx 数学之美 ...

  6. Java微信公众平台开发--番外篇,对GlobalConstants文件的补充

    转自:http://www.cuiyongzhi.com/post/63.html 之前发过一个[微信开发]系列性的文章,也引来了不少朋友观看和点评交流,可能我在写文章时有所疏忽,对部分文件给出的不是 ...

  7. 【转】动态模型及其求解介绍–番外篇

    上一篇文章(中篇)里 面,我用的示意图是因子图,而里面也出现了Psi函数,本来应该当时就解释清楚的,但实在没有精力写那么多东西,所以就想放到下篇讲的.后来发现,讲条件 随机场要结合有向无向图和inde ...

  8. 你所能用到的数据结构之番外篇---逆袭的面向对象(一)

    对于番外篇,我深刻能明白在大多数人眼里就和电视剧的广告一样,说实话,我也不喜欢这种感觉,因为这样会让人觉得是在欺骗消费者啊~~~阿西巴~~~但是我实在发现如果不在这里对面向对象来个入门级的介绍,后面的 ...

  9. 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  10. Python-Matplotlib可视化(番外篇)——Matplotlib中的事件处理详解与实战

    Python-Matplotlib可视化(番外篇)--Matplotlib中的事件处理详解与实战 前言 事件连接 事件属性 实战1:直方图中矩形的拖拽 实战2:鼠标进入和离开 相关链接与参考 前言 在 ...

最新文章

  1. 1.4 微生物对人类社会的影响
  2. 什么样的人不适合做SEO呢
  3. Mybatis的insert方法
  4. ubuntu docker用mount或volume与windows共享文件(samba)(设置共享ip地址)
  5. MongoDB 性能瓶颈分析
  6. Rustup 管理工具
  7. C#读取Excel表格数据到DataGridView中和导出DataGridView中的数据到Excel
  8. mysql添加新用户
  9. Android显存到内存拷贝耗时,memcpy速度太慢?掌握这个技术让内存拷贝效率成倍提升...
  10. 失去循环标记的Python,我这样实现跳出外层循环
  11. 矩阵乘法 c/c++代码
  12. 田志刚:个人知识管理常用软件、工具介绍
  13. Maven到底是个啥?——Maven深入理解
  14. (转)CGJ02、BD09、西安80、北京54、CGCS2000常用坐标系详解
  15. 深度学习baseline模型_深度学习模型在序列标注任务中的应用
  16. 移位运算为什么比乘法除法快
  17. 报错信息:Avoid mutating a prop directly since the value will be overwritten
  18. 数据库设计之商品表分析1
  19. D3.js-基础知识
  20. 2021-08-11 svg基础标签

热门文章

  1. 不同颜色坐标系的坐标转换
  2. 如何批量清理DWG文件?DWG文件清理教程
  3. 我的世界正版验证服务器地址,我的世界1.7.10服务器纯净地址大全
  4. linux文件复制粘贴权限,Linux 文件特殊权限
  5. 控制萤石云摄像头转头
  6. win7 微信 代理服务器设置,手把手为你讲解win7系统电脑登录多个微信的详细方法...
  7. 游戏检测的对抗与防护艺术
  8. windows7 照片查看器无法打开图片, windows提示因为可用内存不足,但我的内存4G?
  9. 阿里maven私服配置和作品上传
  10. Windows 启动 Idea 报错 if you already hava a 64-bit JDK ... 以及 failed to create jvm...