DocValues

DocValues 是一种内部记录字段值的方式,对于某些目的(例如排序和分面)比传统的索引更有效。

为什么使用 DocValues?

Solr 构建索引的标准方法是使用倒排索引。这种方式构建一个在索引中所有文档中找到的词列表,并且在每个词旁边是一个该词出现的文档列表(以及该词在该文档中出现的次数)。这使得搜索速度非常快 - 因为用户按词搜索,所以拥有一个随时可用的词-文档值列表可以加快查询过程。

对于我们现在通常与搜索关联的其他功能(例如排序、分面和高亮显示),这种方法效率不高。例如,分面引擎必须查找构成结果集的每个文档中出现的每个词,并拉取文档 ID 以构建分面列表。在 Solr 中,这是在内存中维护的,并且加载速度可能很慢(取决于文档、词等的数量)。

在 Lucene 4.0 中,引入了一种新方法。DocValue 字段现在是面向列的字段,在索引时构建文档到值的映射。这种方法有望缓解 fieldCache 的一些内存需求,并使分面、排序和分组的查找速度更快。

启用 DocValues

**当使用 schemaVersion >= 1.7** 时,对于大多数支持它们的字段类型,默认启用 DocValues。
  • 原始字段

    • Numeric(不是 DenseVectorField

    • Boolean

    • String

    • Date

    • UUID

    • Enum

  • 排序字段

    • CollationField

    • ICUCollationField

    • SortableTextField

    • SortableBinaryField

  • LatLonPointSpacialField(不是 PointType,它与 PointField 不同)

当使用较早的 schemaVersion (<= 1.6) 时,您只需为将要使用的字段启用 docValues。与所有模式设计一样,您需要定义一个字段类型,然后定义启用 docValues 的该类型的字段。所有这些操作都在 schema 中完成。

为字段启用 docValues 只需要在字段(或字段类型)定义中添加 docValues="true",如 Solr 的 sample_techproducts_configs configset 中的示例所示

<field name="manu_exact" type="string" indexed="false" stored="false" docValues="true" />
如果已将数据索引到 Solr 索引中,则需要在更改模式中的字段定义后完全重新索引内容,以便成功使用 docValues。

DocValues 仅适用于特定字段类型。选择的类型决定了将使用的底层 Lucene docValue 类型。可用的 Solr 字段类型为

  • StrFieldUUIDField

    • 如果该字段是单值的(即,multi-valued 为 false),则 Lucene 将使用 SORTED 类型。

    • 如果该字段是多值的,则 Lucene 将使用 SORTED_SET 类型。条目按排序顺序保存,并删除重复项。

  • 布尔字段(BoolField):

    • 如果该字段是单值的(即,multi-valued 为 false),则 Lucene 将使用 SORTED 类型。

    • 如果该字段是多值的,则 Lucene 将使用 SORTED_SET 类型。条目按排序顺序保存,并删除重复项。

  • 任何 *PointField 数值或日期字段,EnumFieldTypeCurrencyFieldType

    • 如果字段是单值的(即,多值属性为 false),Lucene 将使用 NUMERIC 类型。

    • 如果字段是多值的,Lucene 将使用 SORTED_NUMERIC 类型。条目会保持排序顺序,并且保留重复项。

  • 任何已弃用的 Trie* 数值或日期字段,EnumFieldCurrencyField

    • 如果字段是单值的(即,多值属性为 false),Lucene 将使用 NUMERIC 类型。

    • 如果该字段是多值的,则 Lucene 将使用 SORTED_SET 类型。条目按排序顺序保存,并删除重复项。

这些 Lucene 类型与 值的排序和存储方式相关。

还有一个额外的配置选项可用,即修改字段类型使用的 docValuesFormat。默认实现采用混合方式,将一些内容加载到内存中,并将一些内容保留在磁盘上。但在某些情况下,您可以选择指定另一种 DocValuesFormat 实现。例如,您可以通过在字段类型上指定 docValuesFormat="Direct" 来选择将所有内容都保留在内存中。

<fieldType name="string_in_mem_dv" class="solr.StrField" docValues="true" docValuesFormat="Direct" />

请注意,docValuesFormat 选项可能会在未来的版本中更改。

Lucene 索引的向后兼容性仅支持默认编解码器。如果您选择在模式中自定义 docValuesFormat,则升级到未来版本的 Solr 可能需要您先切换回默认编解码器并优化索引,将其重写为默认编解码器,然后再升级,或者在升级后从头开始重建整个索引。

使用 DocValues

排序、分面和函数

如果字段的 docValues="true",则在任何时候将该字段用于 排序分面函数查询时,都会自动使用 DocValues。

在搜索查询期间检索的字段值通常是从存储的值返回的。但是,当指定返回所有字段(或模式匹配的全局模式,例如“fl=*”)以进行搜索查询时,非存储的 docValues 字段也将与其它存储字段一起返回,具体取决于每个字段的 useDocValuesAsStored 参数的有效值。对于模式版本 >= 1.6,隐式默认值为 useDocValuesAsStored="true"。有关更多详细信息,请参阅 字段类型定义和属性字段

useDocValuesAsStored="false" 时,非存储的 DocValues 字段仍然可以通过在 fl 参数中显式地按名称请求,但不会匹配全局模式("*")。

在查询时返回 DocValues 和“常规”存储字段会产生性能影响,存储字段可能没有这种影响,因为 DocValues 是面向列的,因此检索每个返回的文档可能会产生额外的成本。

从 DocValues 返回非存储字段时,多值字段的值会按排序顺序返回,而不是按插入顺序返回,并且可能会删除重复项,请参见上文。如果您需要按原始插入顺序返回多值字段,请将多值字段存储起来(此更改需要重新索引)。

在查询仅返回 * docValues 字段的情况下,性能可能会提高,因为返回存储字段需要磁盘读取和解压缩,而仅在 fl 列表中返回 docValues 字段仅需要内存访问。

当从其 docValues 形式检索字段时(例如,当使用 /export 处理程序流表达式,或者在 fl 参数中请求字段时),必须了解常规存储字段和 docValues 字段之间的两个重要区别

  1. 顺序*不*保留。在检索存储字段时,插入顺序是返回顺序。对于 docValues,它是*排序后的*顺序。

  2. 对于使用 SORTED_SET 的字段类型(请参见上文),多个相同的条目会合并为一个值。因此,如果插入值 4、5、2、4、1,则返回的值将为 1、2、4、5。

禁用 DocValues

默认情况下,所有支持 DocValues 的字段类型都启用 DocValues(当使用 schemaVersion >= 1.7 时)。在字段或 fieldType 上禁用 docValues 仅需要在定义中添加 docValues="false"

<field name="field_a" type="string" docValues="false" />