前言:

在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类型,一个是数值类型,分词类型在这里没有意义,不再提及:

//数值存储例子  
  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();  

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

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

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

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

最后再提一点,在和solr和es中,如果想要在自己写的插件中读取docvalue的值,读取方法和lucene的差不多,需要注意doule和float的的值转换

作者:random-walk

来源:CSDN

原文:https://blog.csdn.net/asdfsadfasdfsa/article/details/71576750

版权声明:本文为博主原创文章,转载请附上博文链接!

Solr 中的 docValues=true的更多相关文章

  1. Solr中Schema.xml中文版

    <?xml version="1.0" encoding="UTF-8" ?> <!-- Licensed to the Apache Sof ...

  2. 在Solr中配置和使用ansj分词

    在上一节[编译Ansj之Solr插件]中介绍如何编译ansj分词在solr(lucene)环境中使用的接口,本章将介绍如何在solr中使用ansj,其步骤主要包括:下载或者编译ansj和nlp-lan ...

  3. Solr中初学Demo

    import java.util.Collection; import java.util.Date; import org.apache.solr.client.solrj.SolrQuery; i ...

  4. Solr中Field常用属性

    FieldType 实例:<fieldType name="text_ik" class="solr.TextField"></fieldTy ...

  5. Solr 08 - 在Solr Web管理页面中查询索引数据 (Solr中各类查询参数的使用方法)

    目录 1 Solr管理页面的查询入口 2 Solr查询输入框简介 3 Solr管理页面的查询方案 1 Solr管理页面的查询入口 选中需要查询的SolrCore, 然后在菜单栏选择[Query]: 2 ...

  6. Solr 06 - Solr中配置使用IK分词器 (配置schema.xml)

    目录 1 配置中文分词器 1.1 准备IK中文分词器 1.2 配置schema.xml文件 1.3 重启Tomcat并测试 2 配置业务域 2.1 准备商品数据 2.2 配置商品业务域 2.3 配置s ...

  7. Solr中的group与facet的区别

    Solr中的group与facet的区别 如果是简单的使用的话,那么Facet与group都可以用来进行数据的聚合查询,但是他们还是有很大的区别的. 首先上facet跟group的操作: Facet的 ...

  8. solr中Cache综述

    一.概述 Solr查询的核心类就是SolrIndexSearcher,每个core通常在同一时刻只由当前的SolrIndexSearcher供上层的handler使用(当切换SolrIndexSear ...

  9. 如何将数据库中的数据导入到Solr中

    要使用solr实现网站中商品搜索,需要将mysql数据库中数据在solr中创建索引. 1.需要在solr的schema.xml文件定义要存储的商品Field. 商品表中的字段为: 配置内容是: < ...

随机推荐

  1. NET Core2

    NET Core的介绍   .NET Core 是一个通用开发平台,它由微软和开源社区共同管理(git hub的.NET开源社区): 他支持Windows,macOS和Linux,并且可以运行在硬件设 ...

  2. java课后思考题(五)

    1.使用Files. walkFileTree()找出指定文件夹下所有扩展名为.txt和.java的文件. import java.io.IOException;import java.nio.fil ...

  3. 053 Maximum Subarray 最大子序和

    给定一个序列(至少含有 1 个数),从该序列中寻找一个连续的子序列,使得子序列的和最大.例如,给定序列 [-2,1,-3,4,-1,2,1,-5,4],连续子序列 [4,-1,2,1] 的和最大,为 ...

  4. Spring Cloud Hystrix 服务容错保护

    目录 一.Hystrix 是什么 二.Hystrix断路器搭建 三.断路器优化 一.Hystrix 是什么 ​ 在微服务架构中,我们将系统拆分成了若干弱小的单元,单元与单元之间通过HTTP或者TCP等 ...

  5. Could not load file or assembly 'Oracle.ManagedDataAccessDTC.DLL' or one of its dependencies.

    Could not load file or assembly 'Oracle.ManagedDataAccessDTC.DLL' or one of its dependencies.  不是有效的 ...

  6. XML文件的一些操作

    XML 是被设计用来传输和存储数据的, XML 必须含有且仅有一个 根节点元素(没有根节点会报错) 源码下载 http://pan.baidu.com/s/1ge2lpM7 好了,我们 先看一个 XM ...

  7. NHibernate中创建User类报错问题

    前两天刚开始学习NHibernate架构,照着前辈的例子打了一遍运行之后没问题,然后自己创建了一个User的Model发现一运行就报User附近有错误,然后就检查,类写的没错用了virtual,Use ...

  8. Kendo UI 初始化 Data 属性

    初始化 Data 属性 前面在介绍准备 Kendo UI 开发环境时我们使用 jQuery 的方法将一个  HTML 元素转换成一个 Kendo UI 控制项: $(“#datepicker”).ke ...

  9. Cause: java.lang.UnsupportedOperationException

    运行web项目的时候出现以下错误: ### Cause: java.lang.UnsupportedOperationException    at org.mybatis.spring.MyBati ...

  10. HDU - 5457 Hold Your Hand (Trie + 最小割)

    Hold Your Hand Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 65535/102400 K (Java/Others)T ...