Solr中的docValue是什么?我什么时候应该使用它们?

时间:2018-08-20 07:26:18

标签: solr lucene

因此,我已经阅读了多个资料,试图解释Solr中的“ docValues”是什么,但是我似乎不明白何时应该使用它们,尤其是在索引字段与存储字段之间。谁能给我一些启示吗?

4 个答案:

答案 0 :(得分:9)

  

Solr中的docValue是什么?

Doc值可以解释为Lucene的列跨步字段值存储,也可以解释为未反转的索引或前向索引。

用json进行说明:

  • 面向行(存储的字段)

    
    {
    'doc1': {'A':1, 'B':2, 'C':3},
    'doc2': {'A':2, 'B':3, 'C':4},
    'doc3': {'A':4, 'B':3, 'C':2}
    }
    

  • 面向列(docValues)

    
    {
    'A': {'doc1':1, 'doc2':2, 'doc3':4},
    'B': {'doc1':2, 'doc2':3, 'doc3':3},
    'C': {'doc1':3, 'doc2':4, 'doc3':2}
    }
    

  

使用DocValues吗?

存储的字段以大步方式将一个文档的所有字段值存储在一起。在检索中,每个文档一次返回所有字段值,因此加载文档的相关信息非常快。

但是,如果您需要扫描一个字段(进行分面/排序/分组/突出显示),这将是一个缓慢的过程,因为您将不得不遍历所有文档并在每次迭代中加载每个文档的字段,从而导致磁盘搜索

例如,进行排序,找到所有匹配的文档时,Lucene需要获取每个文档的字段值。类似地,例如,构面引擎必须查找将构成结果集的每个文档中出现的每个术语,并提取文档ID以构建构面列表。

现在可以通过两种方式解决此问题:

  • 使用现有的存储字段。在这种情况下,如果您开始在给定的字段上进行排序/汇总,则数据将被懒惰地反转,并在搜索时放入fieldCache中,以便您可以访问给定文档ID的值。此过程占用大量CPU和I / O。
  • DocValues在搜索时非常快速地访问,因为它们以跨步的方式存储,因此每次命中只需要解码该字段的值。这种方法有望减轻fieldCache的一些内存需求,并使查找面,排序和分组的查找变得更快。

就像倒排索引文档值被序列化到磁盘一样,在这种情况下,我们可以依靠操作系统的文件系统缓存来管理内存,而不是在JVM堆上保留结构。

  

我什么时候应该使用它们?

出于上述所有原因。 如果您的内存不足,或者不需要为字段建立索引,则DocValues非常适合进行构面/分组/过滤/排序/函数查询。它们还具有增加您可以进行方面/分组/过滤/排序的字段数的潜力,而不会增加内存需求。我一直在生产Solr中使用docvalues进行排序和构面,并且看到这些查询的性能有了很大的提高。

答案 1 :(得分:4)

@Persimmonium已经解释了DocValues的用例,并且非常清楚。它们非常适用于分面和排序以及IR世界中许多此类奇特的东西。

什么是docValue及其为何存在? docValue只不过是一种建立前向索引的方式,以便文档指向值。它们的建立是为了克服FieldCache的局限性,它提供了在索引时建立的文档到值的映射,并且它们以基于列的方式存储值,并且在文档索引期间完成了所有繁重的工作。

什么是文档值:

与NRT兼容:这些是在索引时构建的按段数据结构,旨在针对数据快速变化的用例进行有效的处理。

基本查询/过滤器支持:您可以对docvalue字段进行基本的词,范围等查询,而无需对其进行索引,但是它们仅是常数得分,通常速度较慢。如果您关心性能和得分,也可以为该字段编制索引。

压缩比字段缓存更好:文档值字段的压缩比字段缓存更好,并且“疯狂”是不可能的。

能够将数据存储在堆内存之外:您可以在fieldType(docValuesFormat =“ Disk”)上指定其他docValuesFormat,以仅在堆上加载最少的数据,而将其他数据结构保留在磁盘上

哪些文档值不是:

不能替代存储的字段 :它们与存储的字段在每种方面都不相关,而是与搜索的数据结构(排序/构面/组/联接/得分)无关。

以这种方式与Lucene docValues一起使用的用例。

    public Bits getDocsWithField(FieldInfo field) throws IOException {
  switch(field.getDocValuesType()) {
    case SORTED_SET:
      return DocValues.docsWithValue(getSortedSet(field), maxDoc);
    case SORTED_NUMERIC:
      return DocValues.docsWithValue(getSortedNumeric(field), maxDoc);
    case SORTED:
      return DocValues.docsWithValue(getSorted(field), maxDoc);
    case BINARY:
      BinaryEntry be = binaries.get(field.number);
      return getMissingBits(be.missingOffset);
    case NUMERIC:
      NumericEntry ne = numerics.get(field.number);
      return getMissingBits(ne.missingOffset);
    default:
      throw new AssertionError();
  }
}

答案 2 :(得分:2)

由于它们的存储和访问方式,它们将加快某些操作,如排序,构面等。

此外,它们是使用某些功能所必需的:流表达式,就地更新...

因此,如有疑问:

  1. 如果索引不大并且大小不是问题,只需启用它们即可。
  2. 如果您的索引确实很大,或者索引性能至关重要,请更仔细地研究它们,并选择启用哪些字段

答案 3 :(得分:0)

我认为这个论坛帖子很好地解释了 docValues 结构面向行和面向列、倒排索引和非倒排索引。 Confusing DocValues documentation