将预先计算的哈希值用于 ElasticSearch 基数聚合(无杂音3 )

Using pre-computed hashes for ElasticSearch cardinality aggregations ( without murmur3 )

提问人:Chris Alexander 提问时间:11/15/2023 最后编辑:Chris Alexander 更新时间:11/15/2023 访问量:38

问:

根据 ElasticSearch 文档,您可以通过在索引文档之前预先计算哈希来提高基数聚合的性能。该文档建议使用 mapper-murmur3 插件,但它也指定您可以在没有插件的情况下从客户端执行此操作。我有一个高基数字符串/关键字字段,我正在对其运行基数聚合,我想探索在没有 murmur3 插件的情况下预先计算哈希的方法。

我的问题如下:

  1. 如果我们在索引之前预先计算哈希值,索引文档中哈希值的数据类型是否重要?是否需要将其散列为长整型或数值类型值/字段,或者是否可以使用基于字符串的关键字字段?

  2. 如果哈希值存储在基于字符串的关键字中,ElasticSearch 如何知道它不需要计算该值的哈希值?如果该值被索引为字符串/关键字字段,它看起来不会像任何其他字符串字段吗?

  3. 最后,预计算哈希值是否对基数聚合的内存使用有有意义的影响,或者主要是速度?我的直觉是,它不会使用预先计算的哈希值使用更少的内存,因为它只是删除了必须计算每个唯一值的哈希值的步骤,但我想我会要求更好地了解它在幕后做了什么。

谢谢!

Elasticsearch OpenSearch 基数

评论


答:

1赞 Val 11/15/2023 #1

在 Elasticsearch 2.x 之前的版本(最高 1.7 版本)中,聚合用于提供 rehash: true/false 标志,允许您指定是否需要在搜索时对运行基数聚合的字段的值进行哈希处理。在字段值已由客户端代码进行哈希处理并以哈希方式存储/索引的情况下使用。然而,当 mapper-murmur3 插件被引入时,这个选项在 2.x 中消失了,因为哈希被认为是廉价的。cardinality

关于 Murmur3,您需要了解的是,它是一种名为 murmur3 的成熟字段类型,通常用作子字段,自动将父字段的值哈希转换为数字哈希(而不是基于字符串的哈希,如 UUID、SHA256 或 MD5)。此外,通常只在高基数字段上使用哈希字段才有意义,而在数值字段或低基数字段上都没有意义,因为在增加磁盘使用率的同时,收益可以忽略不计。murmur3keywordkeyword

因此,如果您决定使用自己的哈希函数预先计算哈希值,则有两种选择:

  1. 您可以使用哈希函数来生成类似于 Murmur3 的数值哈希值
  2. 您可以使用生成字符串哈希值的哈希函数,如果要直接使用该值而不对其进行重新哈希处理,可以配置一个名为(自 8.4 起可用)的特定execution_hint,在这种情况下,它的行为方式与数字哈希完全相同,例如 Murmur3。direct

带有执行提示的基于字符串的哈希字段的示例聚合查询:direct

GET test/_search
{
  "size": 0,
  "aggs": {
    "count": {
      "cardinality": {
        "field": "hash_field",
        "execution_hint": "direct"         <---- add this
      }
    }
  }
}

了解选取如何直接在 CardinalityAggregator 类的源代码中工作也很有趣。

我认为这应该可以回答你上面的所有问题。

评论

0赞 Chris Alexander 11/16/2023
感谢您的出色解释!我最终确实使用了 murmur3 哈希,但这仍然非常有见地。感谢您抽出宝贵时间回复
0赞 Val 11/16/2023
太棒了,我很高兴我能帮上忙!