文档章节

浅谈Lucene中的DocValues

九劫散仙
 九劫散仙
发布于 2016/05/10 19:33
字数 1595
阅读 164
收藏 3

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

Java代码 收藏代码 //数值存储例子
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));

如何读取:

Java代码 收藏代码 //读取索引文件
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默认是全部关闭,比较严谨,大家可酌情开启

Java代码 收藏代码 <fieldname="easy_money"type="double"indexed="true"stored="true"docValues="true" />

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

Java代码 收藏代码 "session_id":{"type":"string","index":"not_analyzed","doc_values":false}

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

有什么问题可以扫码关注微信公众号:我是攻城师(woshigcs),在后台留言咨询。 技术债不能欠,健康债更不能欠, 求道之路,我们同行。

© 著作权归作者所有

共有 人打赏支持
九劫散仙
粉丝 265
博文 175
码字总数 189625
作品 0
海淀
私信 提问
Apache Lucene 4.2 发布,又是全新版本

Apache Lucene 4.2 来了!!! 值得关注的改进内容: Lucene 4.2 使用新的默认编码器 (Lucene42Codec) ,使用更高效的 docvalues 格式,FST 排序,更少的定位开销,改进数值压缩;更小的术语...

oschina
2013/03/12
9.4K
20
基于Lucene查询原理分析Elasticsearch的性能

前言 Elasticsearch是一个很火的分布式搜索系统,提供了非常强大而且易用的查询和分析能力,包括全文索引、模糊查询、多条件组合查询、地理位置查询等等,而且具有一定的分析聚合能力。因为其...

亦征
10/29
0
0
Apache Lucene - Index File Formats V7.3.0

Apache Lucene - Index File Formats(索引文件格式) Introduction(引言) This document defines the index file formats used in this version of Lucene. If you are using a different ver......

囧雪啥都不知道
05/10
0
0
Apache Lucene 6.3.0 发布,Java 搜索引擎

Apache Lucene 6.3.0 发布了。 Lucene 是apache软件基金会一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene的目的...

淡漠悠然
2016/11/09
2.3K
2
Apache Lucene 6.5.1 发布,Java 搜索引擎

Apache Lucene 6.5.1 发布了。Lucene 是 Apache 软件基金会的一个开放源代码的全文检索引擎工具包,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。Lucene ...

局长
2017/04/28
961
0

没有更多内容

加载失败,请刷新页面

加载更多

验证码

response生成验证码 验证码的作用:防止恶意注册、攻击等 网站上看到的验证码,实际上都是一些图片,而这些图片都是程序(Servlet)生成的! package day19.test; import java.awt.Color; i...

码农屌丝
42分钟前
0
0
day147-2018-11-14-英语流利阅读-待学习

《毒液》刚刚上映,创造漫威宇宙的人却走了 雪梨 2018-11-14 1.今日导读 中国的金庸创造了侠义英雄和江湖传奇,而大洋彼岸的斯坦·李也同样创造了一个绚烂璀璨的漫威宇宙,他构思的每个超级英...

飞鱼说编程
43分钟前
3
0
CentOS 安装PHP5和PHP7

安装PHP5 下载解压二进制包 [root@test-a src]# cd /usr/local/src/[root@test-a src]# wget http://cn2.php.net/distributions/php-5.6.32.tar.bz2[root@test-a src]# tar jxvf php-5.6......

野雪球
今天
4
0
修改jfinal默认的redis序列化方式

jfinal 越来越流行, jfinal的redis插件默认的序列化方式是fst。 但是系统中其他项目中用的是spring data redis中的StringRedisTemplate,所有的value都是通过gson转化成String放进去的。 直接...

采蘑菇的大叔
今天
1
2
windows上类似dnsmasq的软件Dual DHCP DNS Server

官网地址:http://dhcp-dns-server.sourceforge.net/官网定向的下载地址:https://sourceforge.net/projects/dhcp-dns-server/files/ 设置参考地址:http://blog.51cto.com/zhukeqiang/18264......

xueyuse0012
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部