前言:
在Lucene4.x之后,出现一个重大的特性,就是索引支持DocValues,这对于广大的solr和elasticsearch用户,无疑来说是一个福音,这玩意的出现通过牺牲一定的磁盘空间带来的好处主要有两个:

(1)节省内存

(2)对排序,分组和一些聚合操作时能够大大提升性能

下面来详细介绍下DocValue的原理和使用场景

(一)什么是DocValues?

DocValues其实是Lucene在构建索引时,会额外建立一个有序的基于document => field value的映射列表;

(二)为什么要用DocValues ?

基于lucene的solr和es都是使用经典的倒排索引模式来达到快速检索的目的,简单的说就是建立 搜索词=》 文档id列表 这样的关系映射,

然后在搜索时,通过类似hash算法,来快速定位到一个搜索关键词,然后读取其的文档id集合,这就是倒排索引的核心思想,这样搜索数据

是非常高效快速的,当然它也是有缺陷的,假如我们需要对数据做一些聚合操作,比如排序,分组时,lucene内部会遍历提取所有出现在文档集合

的排序字段然后再次构建一个最终的排好序的文档集合list,这个步骤的过程全部维持在内存中操作,而且如果排序数据量巨大的话,非常容易就造成solr内存溢出和性能缓慢。

基于这个原因,在lucene4.x之后出现了docvalue这个新特性,在构建索引时会对开启docvalues的字段,额外构建一个已经排
好序的文档到字段级别的一个列式存储映射
,它减轻了在排序和分组时,对内存的依赖,而且大大提升了这个过程的性能,当然它也会耗费的一定的磁盘空间。

(三)什么时候应该用DocValues?

通过上面的剖析,散仙相信大家已经对DocValues有一个初步的了解了,至于它的应用场景,那么也非常明显了,总结起来主要以下几个方面:

1,需要聚合的字段,包括sort,agg,group,facet等

2,需要提供函数查询的字段

3,需要高亮的字段,这个确实能加速,但是散仙并不建议把高亮放在服务端程序做,建议放在前端实现,不容易出错而且总体性能比服务端高

4,需要参与自定义评分的字段,这个稍复杂,大多数人的场景中,不一定能用到,后面会单独写一篇文章介绍。

对于不需要参与上面任何一项的字段,可以选择关闭docvalues,这样可以节省一定的磁盘空间.

(四)DocValues的种类

在lucene的枚举类DocValuesType 中,我们可以看见它声明了六个常量:

1,  NONE  不开启docvalue时的状态

2,  NUMERIC  单个数值类型的docvalue主要包括(int,long,float,double)

3,  BINARY    二进制类型值对应不同的codes最大值可能超过32766字节,

4,  SORTED  有序增量字节存储,仅仅存储不同部分的值和偏移量指针,值必须小于等于32766字节

5,  SORTED_NUMERIC   存储数值类型的有序数组列表

6,  SORTED_SET     可以存储多值域的docvalue值,但返回时,仅仅只能返回多值域的第一个docvalue

通常有四种docvalue存储场景:

A: 字符串或UUID字段+单值 会选择SORTED作为docvalue存储

B: 字符串或UUID字段+多值 会选择SORTED_SET作为docvalue存储

C:数值或日期或枚举字段+单值 会选择NUMERIC 作为docvalue存储

D:数值或日期或枚举字段+多值 会选择SORTED_SET作为docvalue存储

注意,分词字段存储docvalue是没有意义的

(五)如何在Lucene,Solr,ElasticSearch中使用DocValues?

说完了概念方面的东西,下面来点实例的例子,来看下如何给索引加上docsvalue,只要加上docvalues后,排序,分组,聚合的时候

会自动使用docvalue提速,所以我们关注的重点是如何激活docvalue。

1,在原生Lucene中使用DocValues,这个稍麻烦,需要自定义组装,因为lucene是核心算法包,所以封装程度并不是很高,正是

由于这样,理解了lucene之后,再理解solr和elasticsearch是非常easy的。

下面是在lucene中存储docvalue例子,一个是string类型,一个是数值类型,分词类型在这里没有意义,不再提及:

  1. //数值存储例子
  2. FieldType num=new FieldType();
  3. num.setStored(true);//设置存储
  4. num.setIndexOptions(IndexOptions.DOCS);//设置索引类型
  5. num.setNumericType(NumericType.DOUBLE);//数值类型
  6. num.setDocValuesType(DocValuesType.NUMERIC);//DocValue类型
  7. Document doc=new Document();
  8. //添加string字段
  9. doc.add(new SortedDocValuesField("id",new BytesRef("01011")));
  10. //添加数值类型的字段  Float,Doule需要额外转成bit位才能存储,Interger和Long则不需要
  11. doc.add(new DoubleField("price", Double.doubleToRawLongBits(25.258), num));

如何读取:

  1. //读取索引文件
  2. DirectoryReader reader=DirectoryReader.open(FSDirectory.open(Paths.get(indexDir)));
  3. //如果有多个段需要merge成一个,获取第一个进行测试,本例中仅仅就有一个段
  4. SortedDocValues str = DocValues.getSorted(reader.leaves().get(0).reader(), "id");
  5. //数值类型
  6. NumericDocValues db = DocValues.getNumeric(reader.leaves().get(0).reader(), "price");
  7. //读取字符串类型的ByteRef然后打印其内容
  8. System.out.println("id:"+str.get(0).utf8ToString());
  9. //注意此处,要与类型对应,如果是Float,则需要Float.intBitsToFloat((int)db.get(0))进行位数还原
  10. System.out.println("price: "+Double.longBitsToDouble(db.get(0)));
  11. reader.close();

2,在Solr中docvalue默认是全部关闭,比较严谨,大家可酌情开启

  1. <fieldname="easy_money"type="double"indexed="true"stored="true"docValues="true"  />

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

  1. "session_id":{"type":"string","index":"not_analyzed","doc_values":false}

摘自:http://qindongliang.iteye.com/blog/2297280

lucene DocValues——没有看懂的更多相关文章

  1. [转]看懂UML类图

    这里不会将UML的各种元素都提到,我只想讲讲类图中各个类之间的关系: 能看懂类图中各个类之间的线条.箭头代表什么意思后,也就足够应对 日常的工作和交流: 同时,我们应该能将类图所表达的含义和最终的代码 ...

  2. 看懂Oracle执行计划

    最近一直在跟Oracle打交道,从最初的一脸懵逼到现在的略有所知,也来总结一下自己最近所学,不定时更新ing- 一:什么是Oracle执行计划? 执行计划是一条查询语句在Oracle中的执行过程或访问 ...

  3. 一张图看懂ANSYS17.0 流体 新功能与改进

    一张图看懂ANSYS17.0 流体 新功能与改进   提交 我的留言 加载中 已留言   一张图看懂ANSYS17.0 流体 新功能与改进 原创2016-02-03ANSYS模拟在线模拟在线 模拟在线 ...

  4. 怎样看懂Oracle的执行计划

    怎样看懂Oracle的执行计划 一.什么是执行计划 An explain plan is a representation of the access path that is taken when ...

  5. 看懂SqlServer查询计划【转】

    原文链接:http://www.cnblogs.com/fish-li/archive/2011/06/06/2073626.html 开始 SQL Server 查找记录的方法 SQL Server ...

  6. 看懂UML类图

    这里不会将UML的各种元素都提到,我只想讲讲类图中各个类之间的关系: 能看懂类图中各个类之间的线条.箭头代表什么意思后,也就足够应对 日常的工作和交流: 同时,我们应该能将类图所表达的含义和最终的代码 ...

  7. [转]看懂ExtJS的API

    原文地址:http://www.cnblogs.com/youring2/archive/2013/03/05/2944004.html ExtJS的功能很强大,相应的其API也很庞大,并且看起来并不 ...

  8. 看懂UML类图与时序图

    看懂UML类图和时序图 这里不会将UML的各种元素都提到,我只想讲讲类图中各个类之间的关系: 能看懂类图中各个类之间的线条.箭头代表什么意思后,也就足够应对 日常的工作和交流: 同时,我们应该能将类图 ...

  9. 亲子之间,在于看懂,无关耐心zz

    每当有人告诉我:『你对孩子真有耐心!』时,我总会想起我的金项链,当越来越多人说的时候,我就越想找出来,我翻箱倒柜的找,越心急却越找不到,那 一条金项链从我十八岁那一年一直戴在我的脖子上一直到女儿两岁, ...

随机推荐

  1. xtu summer individual 2 E - Double Profiles

    Double Profiles Time Limit: 3000ms Memory Limit: 262144KB This problem will be judged on CodeForces. ...

  2. 杭电ACM省赛集训队选拔赛之热身赛-How Many Tables,并查集模板题~~

    How Many Tables Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  3. 舆论的力量---数学建模初探(SI模型)

    在高中时除了物理竞赛没有学习外,竞赛的五大学科剩下的四门均有所涉猎及参加,因而精力分散太多.因此下定决心大学时可以广泛涉猎知识,但是主攻的竞赛只能有两个ACM和MCM,如今虽然高考完挂,但学术之心尚存 ...

  4. 【cmd】cmd常用命令

    dir 是英文单词directory(目录)的缩写,主要用来显示一个目录下的文件和子目录 md  是英文make directory(创建目录)的缩写 cd  是英文change directory( ...

  5. Python基础教程笔记——第1章

    1.8 函数 pow(x,y) x^y abs(x)          取数的绝对值 round(x)   会把浮点数四舍五入为最接近的整数 floor(x)     向下取整的函数,但是需要先imp ...

  6. HUST 1328 String

    11: KMP next 的强大 题意求前缀在S中出现的次数之和 next[j] 表示 S[0....NEXT[J]]==S[J-NEXT[J].....J]; 于是我们得到..后加入一个字符所得到新 ...

  7. MySql基本数据类型(转)

    说明:通俗的理解:1字节的8位,即1byte=8bit,而这个1byte叫做长度范围,范围的算法是使用bit去求,比如8bit的长度范围是2的8次方,但是在数据库中的类型上是有区分有符号和无符号的,默 ...

  8. cmd的操作命令导出导入.dmp文件

    利用cmd的操作命令导出,详情如下(备注:方法二是转载网上的教程): 1:G:\Oracle\product\10.1.0\Client_1\NETWORK\ADMIN目录下有个tnsname.ora ...

  9. mybatis批量更新两种方式:1.修改值全部一样 2.修改每条记录值不一样

    Mybatis批量更新数据 mybatis批量更新两种方式:1.修改值全部一样 2.修改每条记录值不一样 mybatis批量更新两种方式:1.修改值全部一样 2.修改每条记录值不一样 mybatis批 ...

  10. 虚拟社会(Virtual Society)

    虚拟社会(Virtual Society),又称赛博社会(Cyber Society),是指不同网民之间经由计算机.远程通讯终端等技术设备相互连接起来以进行信息的共享.互动与交流,并在其中进行社会交往 ...