DocValues

DocValues 是一种记录字段值的方式,在某些用途(例如排序和分面)方面比传统索引更高效。

为什么使用 DocValues?

Solr 构建索引的标准方式是使用倒排索引。此样式会构建索引中所有文档中找到的术语列表,每个术语旁边都是术语出现的文档列表(以及术语在该文档中出现的次数)。这使得搜索非常快速 - 由于用户按术语搜索,因此准备好术语到文档值的列表会使查询过程更快。

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

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

启用 DocValues

要使用 docValues,只需为将要与之一起使用的字段启用它。与所有架构设计一样,您需要定义一个字段类型,然后定义启用 docValues 的该类型的字段。所有这些操作都在架构中完成。

为字段启用 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

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

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

  • BoolField:

    • 如果字段是单值的(即,多值是 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。

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

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

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

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

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

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

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

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