前言:

在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. 《深入理解java虚拟机》笔记(5)垃圾回收算法及垃圾收集器

    一.标记-清除算法 算法:分为标记和清除两个阶段,首先标记出所有需要回收的对象,再对标记对象进行回收. 不足之处:效率不高,会产生大量不连续内存碎片,导致下次分配较大内存时,若内存不足不得不触发垃圾回 ...

  2. SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题(一)

    当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异. 笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过5-6篇文章,来介绍一下项目中遇到的问题以及我的解决方 ...

  3. Emacs中自动刷新dired缓冲区

    Emacs中自动刷新dired缓冲区 在dired模式中,如果在不同buffer间切换,buffer不会自动更新,有时还需要手工按“g”键,比较麻烦,如下设置和代码能够在buffer切换和执行shel ...

  4. ERwin DM Reverse Engineer 逆向工程介绍

    介绍内容:利用ERwin DM进行对本地 Oracle 数据库的逆向工程 ERwin DM Version:7.3 ERwin DM 提供两种方式的逆向工程方法,分别是基于脚本文件和基于数据库. 下面 ...

  5. Azure 镜像市场支持一键部署到云

    本视频教程介绍了Azure 镜像市场和一键部署到云. Azure 镜像市场(AMP)由世纪互联运营,是一个联机应用程序和服务市场,它通过独立软件服务商(ISV)能够成为 Azure 客户(Custom ...

  6. redmine安装详解

    1.Linux:centos6.4(32位)2.Gcc的编译环境.使用make命令编辑.yum install gcc-c++ 3.PCRE PCRE(Perl Compatible Regular ...

  7. 数据库要素 ER

    数据库的要素即为ER: 即为表和关系. 再往下即为字段.记录. 往上即为数据操作.管理: 包含多表操作: 在往上为事务. 再往上为大数据.高并发.

  8. [web开发] Vue + spring boot + echart 微博爬虫展示平台

    1.微博登录 2.爬取数据 3.mysql存储 4.pyechart本地展示 5.用vue搭建网站web展示 先放图: 1.微博登录 新浪微博的登录不是简单的post就能解决的,他的登录有加密,所以我 ...

  9. ListView适配器Adapter介绍与优化

    一.ListView与Adapter的关系 ListView是Android开发过程中较为常见的组件之一,它将数据以列表的形式展现出来.一般而言,一个ListView由以下三个元素组成: 1.View ...

  10. Python 模块(二)

    1 logging 模块 logging有两种的配置的方式,configure.logger 1.1 config方式 import logging ''' 日志的配置:config模式 只能选择在屏 ...