DocValues详解

内容纲要

什么是DocValues?

    DocValues是一种记录文档编号到字段值正向关系的列式索引结构,是在Lucene4.0引入的新特性,属于正向索引(又称"正排索引"),在例如排序和Facet查询时,需要通过DocId取字段值的场景下是非常高效的。

为何要使用DocValues?

    solr通常使用倒排索引这种形式的数据结构构建索引,它是搜索召回的核心。倒排索引将所有文档中的字段提取为一个term列表,每个term都对应着一个DocId列表和相应的词频信息。这样的结构使得查询能够非常快速,因为关键词term对应的DocId是现成就有的;但是,利用它来做统计、排序、高亮等操作的时候需要通过DocId来查找field的值却不那么高效了,如facet查询,需查找结果集中每个文档中的每个term,并获取相关的docid以构建facet结果列表。
    在lucene4.0之前,会利用fieldCache在实例启动的时候预先将倒排索引的值load到内存中,问题是,如果文档过多会导致预加载耗费大量时间,还会占用宝贵的内存资源。
    DocValues旨在取代FieldCache在搜索时所发挥的作用,消除搜索时需要加载倒排索引构建FieldCache而引起的性能问题。相当于将FieldCache的构建下推至索引层,以空间换时间,从而获得更高的搜索性能。而正向索引则为搜索结果的排序和统计等搜索结果加工过程提供了有力帮助。

如何启用DocValues?

    启用DocValues很简单,在schema.xml中针对你要启用DocValues添加配置即可,有两种方式:
    1. 基于字段field的方式:直接在字段定义中添加docValues属性为true,如:
<field name="manu_exact" type="string" indexed="false" stored="false" docValues="true" />
    2. 基于字段类型fieldType的方式:在定义字段类型时添加docValues属性为true,如:
<fieldType name="string_in_mem_dv" class="solr.StrField" docValues="true" docValuesFormat="Direct" />
    在基于fieldType的方式定义中,也可配置docValuesFormat属性来指定DocValues的实现类型,如docValuesFormat="Direct"就是将docValues都保存在内存中,详情见下一节介绍;

docValues属性与存储类型属性stored的区别

    可能你会注意到,启用了docValues属性为true的字段(假设字段名为field1),即便stored="false",在使用fl=*或fl=field1的场景下,仍会返回field1,这是因为在schema版本大于等于1.6情况下,默认属性useDocValuesAsStored="true",该属性使得启用docValues属性的字段,不管stored属性是否为true,都能在fl=*或显式指定fl=field1的场景下返回;而在字段field1的属性useDocValuesAsStored="false"情况下,fl=*时则field1不返回,fl=field1时field1仍能返回。
    上述特性使得你可能认为只要启用docValues属性就可以不设置stored="true",但需注意,docValues="true"和stored="true"代表两种截然不同的数据结构,docValues="true"不能替代stored="true"。它们的主要区别如下:
    1. 存储方式:DocValues是列式存储结构,stored="true"是行式存储结构;如果通过fieldId取列的值肯定是用docValues的存储结构更高效。
    docValues="true"的字段保存的值会丢弃索引文档中的顺序,而stored="true"的字段会保留索引文档中的顺序。
    另外,如果在查询时fl中同时返回docValues="true"和stored="true"的字段,由于需要检索每一个返回的文档,较之仅stored="true"的字段,性能上会有一定影响;
    2. 是否分词: stored="true"是不分词的,会将字段原值报存,而docValues="true"的字段保存的值会进行分词;
    3. 适用场景:DocValues适用于sorting/faceting/group/highlight/function queries;而stored="true"适用于需返回该字段的场景

DocValues的实现类型

(1)Memory
    运行时正排数据会全部加载到内存中,这部分数据在内存中是压缩存储的
(2)Direct
    导入到内存中不压缩使用,这个实际使用的效果应该和老版本的fieldCache差不多
(3)SimpleText
    仅供调试使用,不能用于生产环境
(4)Lucene80(默认使用)
    实现方式和Memory的实现方式大同小异,支持的字段类型更加丰富

DocValues的值类型

    Solr弱化了DocValues值的类型,对用户完全屏蔽DocValues的具体类型。实际上它在Lucene是强类型,每种类型的存储结构也不尽相同。DocValues的值有如下5类:
1. Numeric
2. Binary
3. Sorted
4. SortedSet
5. SortedNumeric
    使用哪些类型取决于字段类型:

StrField, UUIDField, BoolField

    若字段为单值,则类型为SORTED
    若字段为多值,则类型为SORTED_SET,去重且有序

PointField/Trie类的数值型,Date型,EnumFieldType,CurrencyFieldType

    若字段为单值,则类型为NUMERIC
    若字段为多值,则类型为SORTED_SET,去重且有序

总结

    DocValues适用于排序、facet、group、高亮、函数式查询的场景,需根据具体场景按需使用

参考文档

  1. https://lucene.apache.org/solr/guide/8_1/docvalues.html
  2. http://www.nosqlnotes.com/technotes/searchengine/lucene-docvalues/

发表评论

邮箱地址不会被公开。 必填项已用*标注